diff --git a/include/osmocom/msc/vlr_sgs.h b/include/osmocom/msc/vlr_sgs.h index 00d52f7b4..fa9d948a1 100644 --- a/include/osmocom/msc/vlr_sgs.h +++ b/include/osmocom/msc/vlr_sgs.h @@ -75,6 +75,7 @@ static inline const char *vlr_sgs_state_counter_name(enum vlr_sgs_state_ctr Ns) /* This callback function is called when an SGs location update is complete */ struct sgs_lu_response { bool accepted; + bool error; struct vlr_subscr *vsub; }; typedef void (*vlr_sgs_lu_response_cb_t) (struct sgs_lu_response *response); diff --git a/src/libmsc/sgs_iface.c b/src/libmsc/sgs_iface.c index d83a730ef..53ab8534a 100644 --- a/src/libmsc/sgs_iface.c +++ b/src/libmsc/sgs_iface.c @@ -376,15 +376,26 @@ static void sgs_tx_loc_upd_resp_cb(struct sgs_lu_response *response) unsigned int new_id_len = 0; uint8_t resp_msg_type; + /* Determine message type that is sent next (needed for logging) */ if (response->accepted) resp_msg_type = SGSAP_MSGT_LOC_UPD_ACK; + else if (response->error) + resp_msg_type = SGSAP_MSGT_RESET_IND; else resp_msg_type = SGSAP_MSGT_LOC_UPD_REJ; + /* Determine MME */ mme = sgs_mme_ctx_by_vsub(vsub, resp_msg_type); if (!mme) return; + /* Handle error (HLR failure) */ + if (response->error) { + osmo_fsm_inst_dispatch(mme->fi, SGS_VLRR_E_START_RESET, NULL); + return; + } + + /* Handle LU accept/reject */ if (response->accepted) { if (vsub->tmsi_new != GSM_RESERVED_TMSI) { new_id_len = gsm48_generate_mid_from_tmsi(new_id, vsub->tmsi_new); @@ -1120,6 +1131,10 @@ static void sgs_vlr_reset_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, reset_params.vlr_name_present = true; reset_ind = gsm29118_create_reset_ind(&reset_params); sgs_tx(sgc, reset_ind); + + /* Perform a reset of the SGS FSM of all subscribers that are present in the VLR */ + vlr_sgs_reset(gsm_network->vlr); + osmo_fsm_inst_state_chg(fi, SGS_VLRR_ST_WAIT_ACK, sgs->cfg.timer[SGS_STATE_TS11], 11); break; default: @@ -1187,6 +1202,7 @@ static const struct osmo_fsm_state sgs_vlr_reset_fsm_states[] = { static struct osmo_fsm sgs_vlr_reset_fsm = { .name = "SGs-VLR-RESET", .states = sgs_vlr_reset_fsm_states, + .num_states = ARRAY_SIZE(sgs_vlr_reset_fsm_states), .allstate_event_mask = S(SGS_VLRR_E_START_RESET), .allstate_action = sgs_vlr_reset_fsm_allstate, .timer_cb = sgs_vlr_reset_fsm_timer_cb, diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index b156b430b..2753096e9 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -854,7 +854,7 @@ static int vlr_subscr_handle_isd_req(struct vlr_subscr *vsub, static int vlr_subscr_handle_lu_res(struct vlr_subscr *vsub, const struct osmo_gsup_message *gsup) { - struct sgs_lu_response sgs_lu_response; + struct sgs_lu_response sgs_lu_response = {0}; bool sgs_lu_in_progress = false; if (vsub->sgs_fsm->state == SGS_UE_ST_LA_UPD_PRES) @@ -885,7 +885,7 @@ static int vlr_subscr_handle_lu_res(struct vlr_subscr *vsub, static int vlr_subscr_handle_lu_err(struct vlr_subscr *vsub, const struct osmo_gsup_message *gsup) { - struct sgs_lu_response sgs_lu_response; + struct sgs_lu_response sgs_lu_response = {0}; bool sgs_lu_in_progress = false; if (vsub->sgs_fsm->state == SGS_UE_ST_LA_UPD_PRES) diff --git a/src/libvlr/vlr_sgs_fsm.c b/src/libvlr/vlr_sgs_fsm.c index 13639ca3c..49ad09a59 100644 --- a/src/libvlr/vlr_sgs_fsm.c +++ b/src/libvlr/vlr_sgs_fsm.c @@ -48,24 +48,6 @@ static const struct value_string sgs_ue_fsm_event_names[] = { {0, NULL} }; -/* Initiate location update and change to SGS_UE_ST_LA_UPD_PRES state */ -static void perform_lu(struct osmo_fsm_inst *fi) -{ - struct vlr_subscr *vsub = fi->priv; - int rc; - osmo_fsm_inst_state_chg(fi, SGS_UE_ST_LA_UPD_PRES, 0, 0); - vsub->ms_not_reachable_flag = false; - - /* Note: At the moment we allocate a new TMSI on each LU. */ - rc = vlr_subscr_alloc_tmsi(vsub); - if (rc != 0) - LOGPFSML(fi, LOGL_ERROR, "(sub %s) VLR LU tmsi allocation failed\n", vlr_subscr_name(vsub)); - - rc = vlr_subscr_req_lu(vsub); - if (rc != 0) - LOGPFSML(fi, LOGL_ERROR, "(sub %s) HLR LU request failed\n", vlr_subscr_name(vsub)); -} - /* Send the SGs Association to NULL state immediately */ static void to_null(struct osmo_fsm_inst *fi) { @@ -86,6 +68,37 @@ static void to_null(struct osmo_fsm_inst *fi) osmo_timer_del(&vsub->sgs.Ts5); } +/* Initiate location update and change to SGS_UE_ST_LA_UPD_PRES state */ +static void perform_lu(struct osmo_fsm_inst *fi) +{ + struct vlr_subscr *vsub = fi->priv; + struct sgs_lu_response sgs_lu_response = {0}; + int rc; + + /* Note: At the moment we allocate a new TMSI on each LU. */ + rc = vlr_subscr_alloc_tmsi(vsub); + if (rc != 0) { + LOGPFSML(fi, LOGL_ERROR, "(sub %s) VLR LU tmsi allocation failed\n", vlr_subscr_name(vsub)); + goto error; + } + + rc = vlr_subscr_req_lu(vsub); + if (rc != 0) { + LOGPFSML(fi, LOGL_ERROR, "(sub %s) HLR LU request failed\n", vlr_subscr_name(vsub)); + goto error; + } + + osmo_fsm_inst_state_chg(fi, SGS_UE_ST_LA_UPD_PRES, 0, 0); + vsub->ms_not_reachable_flag = false; + return; + +error: + to_null(fi); + sgs_lu_response.error = true; + sgs_lu_response.vsub = vsub; + vsub->sgs.response_cb(&sgs_lu_response); +} + /* Respawn a pending paging (Timer is reset and a new paging request is sent) */ static void respawn_paging(struct vlr_subscr *vsub) {