diff options
-rw-r--r-- | include/osmocom/bsc/gsm_data.h | 19 | ||||
-rw-r--r-- | include/osmocom/bsc/lchan_fsm.h | 13 | ||||
-rw-r--r-- | src/osmo-bsc/assignment_fsm.c | 2 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_subscr_conn_fsm.c | 2 | ||||
-rw-r--r-- | src/osmo-bsc/handover_fsm.c | 6 | ||||
-rw-r--r-- | src/osmo-bsc/lchan_fsm.c | 142 | ||||
-rw-r--r-- | src/osmo-bsc/lchan_rtp_fsm.c | 26 | ||||
-rw-r--r-- | src/osmo-bsc/osmo_bsc_bssap.c | 2 |
8 files changed, 105 insertions, 107 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index cf34c6f16..20901420e 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -503,6 +503,19 @@ extern const struct value_string lchan_activate_mode_names[]; static inline const char *lchan_activate_mode_name(enum lchan_activate_mode activ_for) { return get_value_string(lchan_activate_mode_names, activ_for); } +struct lchan_activate_info { + enum lchan_activate_mode activ_for; + struct gsm_subscriber_connection *for_conn; + /* This always is for a specific lchan, so its lchan->type indicates full or half rate. + * When a dyn TS was selected, the lchan->type has been set to the desired rate. */ + enum gsm48_chan_mode chan_mode; + uint16_t s15_s0; + bool requires_voice_stream; + bool wait_before_switching_rtp; /*< true = requires LCHAN_EV_READY_TO_SWITCH_RTP */ + uint16_t msc_assigned_cic; + struct gsm_lchan *re_use_mgw_endpoint_from_lchan; +}; + struct gsm_lchan { /* The TS that we're part of */ struct gsm_bts_trx_ts *ts; @@ -517,18 +530,14 @@ struct gsm_lchan { struct mgwep_ci *mgw_endpoint_ci_bts; struct { - enum lchan_activate_mode activ_for; + struct lchan_activate_info info; bool activ_ack; /*< true as soon as RSL Chan Activ Ack is received */ bool immediate_assignment_sent; /*! This flag ensures that when an lchan activation has succeeded, and we have already * sent ACKs like Immediate Assignment or BSSMAP Assignment Complete, and if other errors * occur later, e.g. during release, that we don't send a NACK out of context. */ bool concluded; - bool requires_voice_stream; - bool wait_before_switching_rtp; /*< true = requires LCHAN_EV_READY_TO_SWITCH_RTP */ - uint16_t msc_assigned_cic; enum gsm0808_cause gsm0808_error_cause; - struct gsm_lchan *re_use_mgw_endpoint_from_lchan; } activate; struct { diff --git a/include/osmocom/bsc/lchan_fsm.h b/include/osmocom/bsc/lchan_fsm.h index 48cd3836a..55ab02400 100644 --- a/include/osmocom/bsc/lchan_fsm.h +++ b/include/osmocom/bsc/lchan_fsm.h @@ -52,19 +52,6 @@ void lchan_fsm_alloc(struct gsm_lchan *lchan); void lchan_release(struct gsm_lchan *lchan, bool do_rr_release, bool err, enum gsm48_rr_cause cause_rr); -struct lchan_activate_info { - enum lchan_activate_mode activ_for; - struct gsm_subscriber_connection *for_conn; - /* This always is for a specific lchan, so its lchan->type indicates full or half rate. - * When a dyn TS was selected, the lchan->type has been set to the desired rate. */ - enum gsm48_chan_mode chan_mode; - uint16_t s15_s0; - bool requires_voice_stream; - bool wait_before_switching_rtp; - uint16_t msc_assigned_cic; - struct gsm_lchan *old_lchan; -}; - void lchan_activate(struct gsm_lchan *lchan, struct lchan_activate_info *info); void lchan_ready_to_switch_rtp(struct gsm_lchan *lchan); diff --git a/src/osmo-bsc/assignment_fsm.c b/src/osmo-bsc/assignment_fsm.c index 93362f85b..a24f7f904 100644 --- a/src/osmo-bsc/assignment_fsm.c +++ b/src/osmo-bsc/assignment_fsm.c @@ -385,7 +385,7 @@ void assignment_fsm_start(struct gsm_subscriber_connection *conn, struct gsm_bts .s15_s0 = req->s15_s0, .requires_voice_stream = conn->assignment.requires_voice_stream, .msc_assigned_cic = req->msc_assigned_cic, - .old_lchan = conn->lchan, + .re_use_mgw_endpoint_from_lchan = conn->lchan, }; lchan_activate(conn->assignment.new_lchan, &info); } diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c index 85e754fa4..c1ac6ebf4 100644 --- a/src/osmo-bsc/bsc_subscr_conn_fsm.c +++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c @@ -550,7 +550,7 @@ bool gscon_connect_mgw_to_msc(struct gsm_subscriber_connection *conn, } else verb = MGCP_VERB_CRCX; - gscon_ensure_mgw_endpoint(conn, for_lchan->activate.msc_assigned_cic); + gscon_ensure_mgw_endpoint(conn, for_lchan->activate.info.msc_assigned_cic); if (!conn->user_plane.mgw_endpoint) { LOGPFSML(conn->fi, LOGL_ERROR, "Unable to allocate endpoint info\n"); diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c index aae50b96a..35f2e5553 100644 --- a/src/osmo-bsc/handover_fsm.c +++ b/src/osmo-bsc/handover_fsm.c @@ -360,7 +360,7 @@ static void handover_start_intra_bsc(struct gsm_subscriber_connection *conn) .chan_mode = conn->lchan->tch_mode, .requires_voice_stream = conn->lchan->mgw_endpoint_ci_bts ? true : false, .msc_assigned_cic = conn->ho.inter_bsc_in.msc_assigned_cic, - .old_lchan = conn->lchan, + .re_use_mgw_endpoint_from_lchan = conn->lchan, .wait_before_switching_rtp = true, }; @@ -706,7 +706,7 @@ static void send_handover_performed(struct gsm_subscriber_connection *conn) ho_perf_params.chosen_encr_alg = lchan->encr.alg_id; ho_perf_params.chosen_encr_alg_present = true; - if (ho->new_lchan->activate.requires_voice_stream) { + if (ho->new_lchan->activate.info.requires_voice_stream) { /* Speech Version (chosen) 3.2.2.51 */ ho_perf_params.speech_version_chosen = gsm0808_permitted_speech(lchan->type, lchan->tch_mode); ho_perf_params.speech_version_chosen_present = true; @@ -1010,7 +1010,7 @@ static void ho_fsm_post_lchan_established(struct osmo_fsm_inst *fi) struct gsm_subscriber_connection *conn = ho_fi_conn(fi); struct handover *ho = &conn->ho; - if (ho->new_lchan->activate.requires_voice_stream + if (ho->new_lchan->activate.info.requires_voice_stream && (ho->scope & HO_INTER_BSC_IN)) ho_fsm_state_chg(HO_ST_WAIT_MGW_ENDPOINT_TO_MSC); else diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c index c87302587..fc1bcbf0c 100644 --- a/src/osmo-bsc/lchan_fsm.c +++ b/src/osmo-bsc/lchan_fsm.c @@ -151,7 +151,7 @@ static void lchan_on_fully_established(struct gsm_lchan *lchan) return; lchan->activate.concluded = true; - switch (lchan->activate.activ_for) { + switch (lchan->activate.info.activ_for) { case FOR_MS_CHANNEL_REQUEST: /* No signalling to do here, MS is free to use the channel, and should go on to connect * to the MSC and establish a subscriber connection. */ @@ -201,7 +201,7 @@ static void lchan_on_fully_established(struct gsm_lchan *lchan) default: LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s fully established\n", - lchan_activate_mode_name(lchan->activate.activ_for)); + lchan_activate_mode_name(lchan->activate.info.activ_for)); break; } } @@ -238,7 +238,7 @@ struct state_timeout lchan_fsm_timeouts[32] = { lchan_set_last_error(_lchan, "lchan %s in state %s: " fmt, \ _lchan->activate.concluded ? "failure" : "allocation failed", \ osmo_fsm_state_name(fsm, state_was), ## args); \ - lchan_on_activation_failure(_lchan, _lchan->activate.activ_for, _lchan->conn); \ + lchan_on_activation_failure(_lchan, _lchan->activate.info.activ_for, _lchan->conn); \ if (fi->state != state_chg) \ lchan_fsm_state_chg(state_chg); \ else \ @@ -481,8 +481,6 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat { struct lchan_activate_info *info = data; struct gsm_lchan *lchan = lchan_fi_lchan(fi); - struct gsm_bts *bts = lchan->ts->trx->bts; - struct gsm48_multi_rate_conf mr_conf; switch (event) { @@ -493,63 +491,8 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat lchan_set_last_error(lchan, NULL); lchan->release.requested = false; - lchan->conn = info->for_conn; - lchan->activate.activ_for = info->activ_for; - lchan->activate.requires_voice_stream = info->requires_voice_stream; - lchan->activate.wait_before_switching_rtp = info->wait_before_switching_rtp; - lchan->activate.msc_assigned_cic = info->msc_assigned_cic; + lchan->activate.info = *info; lchan->activate.concluded = false; - lchan->activate.re_use_mgw_endpoint_from_lchan = info->old_lchan; - - if (info->old_lchan) - lchan->encr = info->old_lchan->encr; - else { - lchan->encr = (struct gsm_encr){ - .alg_id = RSL_ENC_ALG_A5(0), /* no encryption */ - }; - } - - /* If there is a previous lchan, and the new lchan is on the same cell as previous one, - * take over power and TA values. Otherwise, use max power and zero TA. */ - if (info->old_lchan && info->old_lchan->ts->trx->bts == bts) { - lchan->ms_power = info->old_lchan->ms_power; - lchan->bs_power = info->old_lchan->bs_power; - lchan->rqd_ta = info->old_lchan->rqd_ta; - } else { - lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); - /* From lchan_reset(): - * - bs_power is still zero, 0dB reduction, output power = Pn. - * - TA is still zero, to be determined by RACH. */ - } - - if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) { - gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0); - if (lchan_mr_config(lchan, &mr_conf) < 0) { - lchan_fail("Can not generate multirate configuration IE\n"); - return; - } - } - - switch (info->chan_mode) { - - case GSM48_CMODE_SIGN: - lchan->rsl_cmode = RSL_CMOD_SPD_SIGN; - lchan->tch_mode = GSM48_CMODE_SIGN; - break; - - case GSM48_CMODE_SPEECH_V1: - case GSM48_CMODE_SPEECH_EFR: - case GSM48_CMODE_SPEECH_AMR: - lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH; - lchan->tch_mode = info->chan_mode; - break; - - default: - lchan_fail("Not implemented: cannot activate for chan mode %s", - gsm48_chan_mode_name(info->chan_mode)); - return; - } - lchan_fsm_state_chg(LCHAN_ST_WAIT_TS_READY); break; @@ -561,18 +504,75 @@ static void lchan_fsm_unused(struct osmo_fsm_inst *fi, uint32_t event, void *dat static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { struct gsm_lchan *lchan = lchan_fi_lchan(fi); - struct mgwep_ci *use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan); + struct gsm48_multi_rate_conf mr_conf; + struct gsm_bts *bts = lchan->ts->trx->bts; + struct mgwep_ci *use_mgwep_ci; + struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan; + struct lchan_activate_info *info = &lchan->activate.info; if (lchan->release.requested) { lchan_fail("Release requested while activating"); return; } + lchan->conn = info->for_conn; + + if (old_lchan) + lchan->encr = old_lchan->encr; + else { + lchan->encr = (struct gsm_encr){ + .alg_id = RSL_ENC_ALG_A5(0), /* no encryption */ + }; + } + + /* If there is a previous lchan, and the new lchan is on the same cell as previous one, + * take over power and TA values. Otherwise, use max power and zero TA. */ + if (old_lchan && old_lchan->ts->trx->bts == bts) { + lchan->ms_power = old_lchan->ms_power; + lchan->bs_power = old_lchan->bs_power; + lchan->rqd_ta = old_lchan->rqd_ta; + } else { + lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power); + /* From lchan_reset(): + * - bs_power is still zero, 0dB reduction, output power = Pn. + * - TA is still zero, to be determined by RACH. */ + } + + if (info->chan_mode == GSM48_CMODE_SPEECH_AMR) { + gsm48_mr_cfg_from_gsm0808_sc_cfg(&mr_conf, info->s15_s0); + if (lchan_mr_config(lchan, &mr_conf) < 0) { + lchan_fail("Can not generate multirate configuration IE\n"); + return; + } + } + + switch (info->chan_mode) { + + case GSM48_CMODE_SIGN: + lchan->rsl_cmode = RSL_CMOD_SPD_SIGN; + lchan->tch_mode = GSM48_CMODE_SIGN; + break; + + case GSM48_CMODE_SPEECH_V1: + case GSM48_CMODE_SPEECH_EFR: + case GSM48_CMODE_SPEECH_AMR: + lchan->rsl_cmode = RSL_CMOD_SPD_SPEECH; + lchan->tch_mode = info->chan_mode; + break; + + default: + lchan_fail("Not implemented: cannot activate for chan mode %s", + gsm48_chan_mode_name(info->chan_mode)); + return; + } + + use_mgwep_ci = lchan_use_mgw_endpoint_ci_bts(lchan); + LOG_LCHAN(lchan, LOGL_INFO, "Activation requested: %s voice=%s MGW-ci=%s type=%s tch-mode=%s\n", - lchan_activate_mode_name(lchan->activate.activ_for), - lchan->activate.requires_voice_stream ? "yes" : "no", - lchan->activate.requires_voice_stream ? + lchan_activate_mode_name(lchan->activate.info.activ_for), + lchan->activate.info.requires_voice_stream ? "yes" : "no", + lchan->activate.info.requires_voice_stream ? (use_mgwep_ci ? mgwep_ci_name(use_mgwep_ci) : "new") : "none", gsm_lchant_name(lchan->type), @@ -583,7 +583,7 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p osmo_fsm_inst_dispatch(lchan->ts->fi, TS_EV_LCHAN_REQUESTED, lchan); /* Prepare an MGW endpoint CI if appropriate. */ - if (lchan->activate.requires_voice_stream) + if (lchan->activate.info.requires_voice_stream) lchan_rtp_fsm_start(lchan); } @@ -627,7 +627,7 @@ static void lchan_fsm_wait_activ_ack_onenter(struct osmo_fsm_inst *fi, uint32_t return; } - switch (lchan->activate.activ_for) { + switch (lchan->activate.info.activ_for) { case FOR_MS_CHANNEL_REQUEST: act_type = RSL_ACT_INTRA_IMM_ASS; break; @@ -709,7 +709,7 @@ static void lchan_fsm_post_activ_ack(struct osmo_fsm_inst *fi) return; } - switch (lchan->activate.activ_for) { + switch (lchan->activate.info.activ_for) { case FOR_MS_CHANNEL_REQUEST: rc = rsl_tx_imm_assignment(lchan); @@ -764,7 +764,7 @@ static void lchan_fsm_post_activ_ack(struct osmo_fsm_inst *fi) default: LOG_LCHAN(lchan, LOGL_NOTICE, "lchan %s is now active\n", - lchan_activate_mode_name(lchan->activate.activ_for)); + lchan_activate_mode_name(lchan->activate.info.activ_for)); break; } @@ -784,7 +784,7 @@ static void lchan_fsm_wait_rll_rtp_establish(struct osmo_fsm_inst *fi, uint32_t switch (event) { case LCHAN_EV_RLL_ESTABLISH_IND: - if (!lchan->activate.requires_voice_stream + if (!lchan->activate.info.requires_voice_stream || lchan_rtp_established(lchan)) lchan_fsm_state_chg(LCHAN_ST_ESTABLISHED); return; @@ -1381,6 +1381,8 @@ void lchan_forget_conn(struct gsm_lchan *lchan) if (!lchan) return; + lchan->activate.info.for_conn = NULL; + conn = lchan->conn; if (conn) { /* Log for both lchan FSM and conn FSM to ease reading the log in case of problems */ diff --git a/src/osmo-bsc/lchan_rtp_fsm.c b/src/osmo-bsc/lchan_rtp_fsm.c index 6ab3da4d9..84cc28729 100644 --- a/src/osmo-bsc/lchan_rtp_fsm.c +++ b/src/osmo-bsc/lchan_rtp_fsm.c @@ -111,9 +111,9 @@ void lchan_rtp_fsm_start(struct gsm_lchan *lchan) /* Use old lchan only if there is an MGW endpoint present. Otherwise, on ROLLBACK, we might put * an endpoint "back" to an lchan that never had one to begin with. */ - if (lchan->activate.re_use_mgw_endpoint_from_lchan - && !lchan->activate.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts) - lchan->activate.re_use_mgw_endpoint_from_lchan = NULL; + if (lchan->activate.info.re_use_mgw_endpoint_from_lchan + && !lchan->activate.info.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts) + lchan->activate.info.re_use_mgw_endpoint_from_lchan = NULL; lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_MGW_ENDPOINT_AVAILABLE); } @@ -127,8 +127,8 @@ struct mgwep_ci *lchan_use_mgw_endpoint_ci_bts(struct gsm_lchan *lchan) return lchan->mgw_endpoint_ci_bts; if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED)) return NULL; - if (lchan->activate.re_use_mgw_endpoint_from_lchan) - return lchan->activate.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts; + if (lchan->activate.info.re_use_mgw_endpoint_from_lchan) + return lchan->activate.info.re_use_mgw_endpoint_from_lchan->mgw_endpoint_ci_bts; return NULL; } @@ -147,7 +147,7 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_available_onenter(struct osmo_fsm_in return; } - mgwep = gscon_ensure_mgw_endpoint(lchan->conn, lchan->activate.msc_assigned_cic); + mgwep = gscon_ensure_mgw_endpoint(lchan->conn, lchan->activate.info.msc_assigned_cic); if (!mgwep) { lchan_rtp_fail("Internal error: cannot obtain MGW endpoint handle for conn"); return; @@ -232,7 +232,7 @@ static void lchan_rtp_fsm_switch_rtp(struct osmo_fsm_inst *fi) { struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi); - if (lchan->activate.wait_before_switching_rtp) { + if (lchan->activate.info.wait_before_switching_rtp) { LOG_LCHAN_RTP(lchan, LOGL_DEBUG, "Waiting for an event by caller before switching RTP\n"); lchan_rtp_fsm_state_chg(LCHAN_RTP_ST_WAIT_READY_TO_SWITCH_RTP); @@ -305,7 +305,7 @@ static void lchan_rtp_fsm_wait_ipacc_crcx_ack(struct osmo_fsm_inst *fi, uint32_t return; case LCHAN_RTP_EV_READY_TO_SWITCH_RTP: - lchan->activate.wait_before_switching_rtp = false; + lchan->activate.info.wait_before_switching_rtp = false; return; case LCHAN_RTP_EV_RELEASE: @@ -365,7 +365,7 @@ static void lchan_rtp_fsm_wait_ipacc_mdcx_ack(struct osmo_fsm_inst *fi, uint32_t return; case LCHAN_RTP_EV_READY_TO_SWITCH_RTP: - lchan->activate.wait_before_switching_rtp = false; + lchan->activate.info.wait_before_switching_rtp = false; return; case LCHAN_RTP_EV_RELEASE: @@ -437,7 +437,7 @@ static void lchan_rtp_fsm_wait_mgw_endpoint_configured_onenter(struct osmo_fsm_i uint32_t prev_state) { struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi); - struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan; + struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan; if (lchan->release.requested) { lchan_rtp_fail("Release requested while activating"); @@ -514,7 +514,7 @@ static void lchan_rtp_fsm_ready(struct osmo_fsm_inst *fi, uint32_t event, void * static void lchan_rtp_fsm_rollback_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) { struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi); - struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan; + struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan; if (!lchan->mgw_endpoint_ci_bts || !old_lchan) { osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, 0); @@ -526,7 +526,7 @@ static void lchan_rtp_fsm_rollback_onenter(struct osmo_fsm_inst *fi, uint32_t pr static void lchan_rtp_fsm_rollback(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi); - struct gsm_lchan *old_lchan = lchan->activate.re_use_mgw_endpoint_from_lchan; + struct gsm_lchan *old_lchan = lchan->activate.info.re_use_mgw_endpoint_from_lchan; switch (event) { @@ -560,7 +560,7 @@ static void lchan_rtp_fsm_established_onenter(struct osmo_fsm_inst *fi, uint32_t struct gsm_lchan *lchan = lchan_rtp_fi_lchan(fi); /* Make sure that we will not hand back the MGW endpoint to any old lchan from here on. */ - lchan->activate.re_use_mgw_endpoint_from_lchan = NULL; + lchan->activate.info.re_use_mgw_endpoint_from_lchan = NULL; } static void lchan_rtp_fsm_established(struct osmo_fsm_inst *fi, uint32_t event, void *data) diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c index 60ec5fbf2..f2ccf2cf1 100644 --- a/src/osmo-bsc/osmo_bsc_bssap.c +++ b/src/osmo-bsc/osmo_bsc_bssap.c @@ -1101,7 +1101,7 @@ enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection }; /* speech_codec_chosen */ - if (ho->new_lchan->activate.requires_voice_stream && gscon_is_aoip(conn)) { + if (ho->new_lchan->activate.info.requires_voice_stream && gscon_is_aoip(conn)) { int perm_spch = gsm0808_permitted_speech(lchan->type, lchan->tch_mode); params.speech_codec_chosen_present = true; rc = gsm0808_speech_codec_from_chan_type(¶ms.speech_codec_chosen, perm_spch); |