diff options
Diffstat (limited to 'src/osmo-bsc/gsm_08_08.c')
-rw-r--r-- | src/osmo-bsc/gsm_08_08.c | 104 |
1 files changed, 56 insertions, 48 deletions
diff --git a/src/osmo-bsc/gsm_08_08.c b/src/osmo-bsc/gsm_08_08.c index ce7606f28..a2bab4bed 100644 --- a/src/osmo-bsc/gsm_08_08.c +++ b/src/osmo-bsc/gsm_08_08.c @@ -26,6 +26,7 @@ #include <osmocom/bsc/gsm_08_08.h> #include <osmocom/bsc/codec_pref.h> #include <osmocom/bsc/lchan_fsm.h> +#include <osmocom/bsc/bsc_stats.h> #include <osmocom/bsc/gsm_04_08_rr.h> #include <osmocom/bsc/a_reset.h> @@ -34,6 +35,7 @@ #include <osmocom/bsc/lcs_loc_req.h> #include <osmocom/gsm/protocol/gsm_08_08.h> +#include <osmocom/gsm/protocol/gsm_04_08.h> #include <osmocom/gsm/gsm0808.h> #include <osmocom/gsm/mncc.h> #include <osmocom/gsm/gsm48.h> @@ -69,21 +71,23 @@ void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, { int rc; struct msgb *resp; + struct gsm_bts *bts; if (!msc_connected(conn)) return; - LOGP(DMSC, LOGL_NOTICE, "Tx MSC SAPI N REJECT (dlci=0x%02x, cause='%s')\n", - dlci, gsm0808_cause_name(cause)); + bts = conn_get_bts(conn); + LOG_BTS(bts, DMSC, LOGL_NOTICE, "Tx MSC SAPI N REJECT (dlci=0x%02x, cause='%s')\n", + dlci, gsm0808_cause_name(cause)); resp = gsm0808_create_sapi_reject_cause(dlci, cause); - rate_ctr_inc(&conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_SAPI_N_REJECT]); + rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_SAPI_N_REJECT)); rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp); if (rc != 0) msgb_free(resp); } /*! MS->MSC: Tell MSC that ciphering has been enabled. */ -void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) +void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_a5_n) { int rc; struct msgb *resp; @@ -92,30 +96,13 @@ void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb * return; LOGP(DMSC, LOGL_DEBUG, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n"); - resp = gsm0808_create_cipher_complete(msg, chosen_encr); - rate_ctr_inc(&conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_CIPHER_COMPLETE]); + resp = gsm0808_create_cipher_complete(msg, ALG_A5_NR_TO_BSSAP(chosen_a5_n)); + rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CIPHER_COMPLETE)); rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp); if (rc != 0) msgb_free(resp); } -/* 9.2.5 CM service accept */ -int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn) -{ - struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACK"); - struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); - - msg->lchan = conn->lchan; - - gh->proto_discr = GSM48_PDISC_MM; - gh->msg_type = GSM48_MT_MM_CM_SERV_ACC; - - DEBUGP(DMM, "-> CM SERVICE ACK\n"); - - gscon_submit_rsl_dtap(conn, msg, 0, 0); - return 0; -} - static bool is_cm_service_for_emerg(struct msgb *msg) { struct gsm48_service_request *cm; @@ -232,7 +219,7 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, if (nri_matches_msc) { LOG_NRI(LOGL_DEBUG, "matches msc %d, but this MSC is currently not connected\n", msc->nr); - rate_ctr_inc(&msc->msc_ctrs->ctr[MSC_CTR_MSCPOOL_SUBSCR_ATTACH_LOST]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc->msc_ctrs, MSC_CTR_MSCPOOL_SUBSCR_ATTACH_LOST)); } continue; } @@ -244,10 +231,10 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, msc->nr); } else { LOG_NRI(LOGL_DEBUG, "matches msc %d\n", msc->nr); - rate_ctr_inc(&msc->msc_ctrs->ctr[MSC_CTR_MSCPOOL_SUBSCR_KNOWN]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc->msc_ctrs, MSC_CTR_MSCPOOL_SUBSCR_KNOWN)); if (is_emerg) { - rate_ctr_inc(&msc->msc_ctrs->ctr[MSC_CTR_MSCPOOL_EMERG_FORWARDED]); - rate_ctr_inc(&bsc_gsmnet->bsc_ctrs->ctr[BSC_CTR_MSCPOOL_EMERG_FORWARDED]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc->msc_ctrs, MSC_CTR_MSCPOOL_EMERG_FORWARDED)); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->bsc_ctrs, BSC_CTR_MSCPOOL_EMERG_FORWARDED)); } return msc; } @@ -282,9 +269,9 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, * them are usable -- wrap to the start. */ msc_target = msc_round_robin_next ? : msc_round_robin_first; if (!msc_target) { - rate_ctr_inc(&bsc_gsmnet->bsc_ctrs->ctr[BSC_CTR_MSCPOOL_SUBSCR_NO_MSC]); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->bsc_ctrs, BSC_CTR_MSCPOOL_SUBSCR_NO_MSC)); if (is_emerg) - rate_ctr_inc(&bsc_gsmnet->bsc_ctrs->ctr[BSC_CTR_MSCPOOL_EMERG_LOST]); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->bsc_ctrs, BSC_CTR_MSCPOOL_EMERG_LOST)); return NULL; } @@ -292,13 +279,13 @@ static struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, osmo_mobile_identity_to_str_c(OTC_SELECT, mi), msc_target->nr); if (is_null_nri) - rate_ctr_inc(&msc_target->msc_ctrs->ctr[MSC_CTR_MSCPOOL_SUBSCR_REATTACH]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc_target->msc_ctrs, MSC_CTR_MSCPOOL_SUBSCR_REATTACH)); else - rate_ctr_inc(&msc_target->msc_ctrs->ctr[MSC_CTR_MSCPOOL_SUBSCR_NEW]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc_target->msc_ctrs, MSC_CTR_MSCPOOL_SUBSCR_NEW)); if (is_emerg) { - rate_ctr_inc(&msc_target->msc_ctrs->ctr[MSC_CTR_MSCPOOL_EMERG_FORWARDED]); - rate_ctr_inc(&bsc_gsmnet->bsc_ctrs->ctr[BSC_CTR_MSCPOOL_EMERG_FORWARDED]); + rate_ctr_inc(rate_ctr_group_get_ctr(msc_target->msc_ctrs, MSC_CTR_MSCPOOL_EMERG_FORWARDED)); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->bsc_ctrs, BSC_CTR_MSCPOOL_EMERG_FORWARDED)); } /* An MSC was picked by round-robin, so update the next round-robin nr to pick */ @@ -346,6 +333,7 @@ static void parse_powercap(struct gsm_subscriber_connection *conn, struct msgb * /* No power cap in other messages */ return; } + break; /* FIXME: pwr_lev in Paging Response? */ default: /* No power cap in other messages */ @@ -401,11 +389,10 @@ int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_chan if (osmo_mobile_identity_decode_from_l3(&mi, msg, false)) { LOG_COMPL_L3(pdisc, mtype, LOGL_ERROR, "Cannot extract Mobile Identity: %s\n", msgb_hexdump_c(OTC_SELECT, msg)); - /* Likely this is an invalid Complete Layer 3 message that deserves to be rejected. However, the current - * state of our ttcn3 tests does send invalid Layer 3 Info in some tests and expects osmo-bsc to not - * care about that. So, changing the behavior to rejecting on missing MI causes test failure and, if at - * all, should happen in a separate patch. - * See e.g. BSC_Tests.TC_chan_rel_rll_rel_ind: "dt := * f_est_dchan('23'O, 23, '00010203040506'O);" + /* Likely this is an invalid Complete Layer 3 message that deserves to be rejected. However, the BSC is + * not expected to look at this layer so it's duty of the MSC to reject it. + * Hence, keep on going with the conn without an assigned bsc_subscr, forwarding the L3 to the MSC and + * letting it take decision on the matter. */ } else { bsub = bsc_subscr_find_or_create_by_mi(bsc_gsmnet->bsc_subscribers, &mi, __func__); @@ -413,8 +400,13 @@ int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_chan /* If this Mobile Identity already has an active bsc_subscr, look whether there also is an active A-interface * conn for this subscriber. This may be the case during a Perform Location Request (LCS) from the MSC that - * started on an IDLE MS, and now the MS is becoming active. Associate with the existing conn. */ - if (bsub) + * started on an IDLE MS, and now the MS is becoming active. Associate with the existing conn. + * + * However, for a CM Re-Establishment Request, we must *not* re-use the existing conn, but allocate a second + * conn for the same bsub. The previous conn will be Clear'ed by the MSC as soon as it receives the L3 Complete + * message == the CM Re-Establishment Request. + */ + if (bsub && !(pdisc == GSM48_PDISC_MM && mtype == GSM48_MT_MM_CM_REEST_REQ)) conn = bsc_conn_by_bsub(bsub); if (!conn) { @@ -447,7 +439,10 @@ int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_chan paged_from_msc = NULL; paging_reasons = BSC_PAGING_NONE; if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP) { - paging_request_stop(&paged_from_msc, &paging_reasons, bts, conn->bsub); + /* It only makes sense to attempt to find a pending paging request if the subscriber from the + * Paging Response can be identified (bsub != NULL). */ + if (conn->bsub) + paging_request_stop(&paged_from_msc, &paging_reasons, bts, conn->bsub); if (!paged_from_msc) { /* This looks like an unsolicited Paging Response. It is required to pick any MSC, because any * MT-CSFB calls were Paged by the MSC via SGs, and hence are not listed in the BSC. */ @@ -455,12 +450,12 @@ int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_chan "%s Unsolicited Paging Response, possibly an MT-CSFB call.\n", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi)); - rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_PAGING_NO_ACTIVE_PAGING]); - rate_ctr_inc(&bsc_gsmnet->bsc_ctrs->ctr[BSC_CTR_PAGING_NO_ACTIVE_PAGING]); + rate_ctr_inc(rate_ctr_group_get_ctr(bts->bts_ctrs, BTS_CTR_PAGING_NO_ACTIVE_PAGING)); + rate_ctr_inc(rate_ctr_group_get_ctr(bsc_gsmnet->bsc_ctrs, BSC_CTR_PAGING_NO_ACTIVE_PAGING)); } else if (is_msc_usable(paged_from_msc, is_emerg)) { LOG_COMPL_L3(pdisc, mtype, LOGL_DEBUG, "%s matches earlier Paging from msc %d\n", osmo_mobile_identity_to_str_c(OTC_SELECT, &mi), paged_from_msc->nr); - rate_ctr_inc(&paged_from_msc->msc_ctrs->ctr[MSC_CTR_MSCPOOL_SUBSCR_PAGED]); + rate_ctr_inc(rate_ctr_group_get_ctr(paged_from_msc->msc_ctrs, MSC_CTR_MSCPOOL_SUBSCR_PAGED)); } else { LOG_COMPL_L3(pdisc, mtype, LOGL_DEBUG, "%s matches earlier Paging from msc %d, but this MSC is not connected\n", @@ -539,11 +534,13 @@ int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_chan early_exit: if (release_lchan) - lchan_release(lchan, false, true, RSL_ERR_EQUIPMENT_FAIL); + lchan_release(lchan, true, true, RSL_ERR_EQUIPMENT_FAIL, + gscon_last_eutran_plmn(conn)); log_set_context(LOG_CTX_BSC_SUBSCR, NULL); return rc; } + /*! MS->BSC/MSC: Um L3 message. */ void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) { @@ -556,8 +553,9 @@ void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct ms parse_powercap(conn, msg); - /* Store link_id in msg->cb */ - OBSC_LINKID_CB(msg) = link_id; + /* convert RSL link ID to DLCI, store in msg->cb */ + OBSC_LINKID_CB(msg) = RSL_LINK_ID2DLCI(link_id); + osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_MO_DTAP, msg); done: log_set_context(LOG_CTX_BSC_SUBSCR, NULL); @@ -590,10 +588,20 @@ void bsc_cm_update(struct gsm_subscriber_connection *conn, } conn_update_ms_power_class(conn, rc8); + if (cm3 != NULL && cm3_len > 0) { + rc = gsm48_decode_classmark3(&conn->cm3, cm3, cm3_len); + if (rc < 0) { + LOGP(DMSC, LOGL_NOTICE, "Unable to decode classmark3 during CM Update.\n"); + memset(&conn->cm3, 0, sizeof(conn->cm3)); + conn->cm3_valid = false; + } else + conn->cm3_valid = true; + } + if (!msc_connected(conn)) return; - rate_ctr_inc(&conn->sccp.msc->msc_ctrs->ctr[MSC_CTR_BSSMAP_TX_DT1_CLASSMARK_UPDATE]); + rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CLASSMARK_UPDATE)); resp = gsm0808_create_classmark_update(cm2, cm2_len, cm3, cm3_len); rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp); if (rc != 0) |