Change in osmo-msc[master]: Fill Last Used E-UTRAN PLMN Id when in CSFB

pespin gerrit-no-reply at lists.osmocom.org
Thu Apr 29 12:41:25 UTC 2021


pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-msc/+/23915 )

Change subject: Fill Last Used E-UTRAN PLMN Id when in CSFB
......................................................................

Fill Last Used E-UTRAN PLMN Id when in CSFB

Since recently, osmo-bsc behaves strictly as per specs, meaning it will
only send the "Cell selection indicator after release of all TCH and SDCCH IE"
in RR Channel Release iff:
* "Last Used E-UTRAN PLMN Id" was received in the CommonID sent MSC->BSC
* "Last Used E-UTRAN PLMN Id" was received insider "old BSS to new BSS Information"
  in the HandoverRequest sent MSC->BSC.
On the other hand, CSFB_Indicator from ClearCommand MSC->BSC is nw
ignored and not taken into account.

Hence, let's update osmo-msc to also behave correctly by sending the
Last Used E-UTRAN PLMN ID at CommonID tx time to avoid regressions in
CSFB support when running against newer osmo-bsc.

Let's keep sending the CSFB Indicator in ClearCommand as we used too, in
order to keep compatibility with older BSCs (as per spec).

Related: SYS#5337
Change-Id: Ic5f175b179973d0a50d94f00e15f5a3e332605fc
---
M include/osmocom/msc/ran_msg.h
M include/osmocom/msc/vlr.h
M include/osmocom/msc/vlr_sgs.h
M src/libmsc/gsm_04_08.c
M src/libmsc/msc_a.c
M src/libmsc/ran_msg_a.c
M src/libmsc/sgs_iface.c
M src/libvlr/vlr.c
M src/libvlr/vlr_sgs.c
9 files changed, 86 insertions(+), 5 deletions(-)

Approvals:
  fixeria: Looks good to me, but someone else must approve
  pespin: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h
index 3b08b46..1303ba3 100644
--- a/include/osmocom/msc/ran_msg.h
+++ b/include/osmocom/msc/ran_msg.h
@@ -220,6 +220,8 @@
 		} cipher_mode_reject;
 		struct {
 			const char *imsi;
+			bool last_eutran_plmn_present;
+			struct osmo_plmn_id last_eutran_plmn;
 		} common_id;
 		struct {
 			enum gsm48_reject_value cause;
diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h
index 3b9bbc4..6e65283 100644
--- a/include/osmocom/msc/vlr.h
+++ b/include/osmocom/msc/vlr.h
@@ -193,6 +193,8 @@
 		vlr_sgs_lu_mminfo_cb_t mminfo_cb;
 		enum sgsap_service_ind paging_serv_ind;
 		struct osmo_timer_list Ts5;
+		bool last_eutran_plmn_present;
+		struct osmo_plmn_id last_eutran_plmn;
 	} sgs;
 
 	struct osmo_gsm48_classmark classmark;
@@ -398,6 +400,8 @@
 void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei);
 void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv);
 void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn);
+void vlr_subscr_set_last_used_eutran_plmn_id(struct vlr_subscr *vsub,
+					     const struct osmo_plmn_id *last_eutran_plmn);
 
 bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi);
 bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi);
diff --git a/include/osmocom/msc/vlr_sgs.h b/include/osmocom/msc/vlr_sgs.h
index fa9d948..1a4984d 100644
--- a/include/osmocom/msc/vlr_sgs.h
+++ b/include/osmocom/msc/vlr_sgs.h
@@ -97,7 +97,7 @@
 int vlr_sgs_loc_update(struct vlr_instance *vlr, struct vlr_sgs_cfg *cfg,
 		       vlr_sgs_lu_response_cb_t response_cb, vlr_sgs_lu_paging_cb_t paging_cb,
 		       vlr_sgs_lu_mminfo_cb_t mminfo_cb, char *mme_name, enum vlr_lu_type type, const char *imsi,
-		       struct osmo_location_area_id *new_lai);
+		       struct osmo_location_area_id *new_lai, struct osmo_plmn_id *last_eutran_plmn);
 void vlr_sgs_loc_update_acc_sent(struct vlr_subscr *vsub);
 void vlr_sgs_loc_update_rej_sent(struct vlr_subscr *vsub);
 void vlr_sgs_detach(struct vlr_instance *vlr, const char *imsi, bool eps);
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index 6379059..58ef074 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -1368,12 +1368,19 @@
 static int msc_vlr_tx_common_id(void *msc_conn_ref)
 {
 	struct msc_a *msc_a = msc_conn_ref;
+	struct vlr_subscr *vsub = msc_a_vsub(msc_a);
 	struct ran_msg msg = {
 		.msg_type = RAN_MSG_COMMON_ID,
 		.common_id = {
-			.imsi = msc_a_vsub(msc_a)->imsi,
+			.imsi = vsub->imsi,
+			.last_eutran_plmn_present = vsub->sgs.last_eutran_plmn_present,
 		},
 	};
+	if (vsub->sgs.last_eutran_plmn_present) {
+		memcpy(&msg.common_id.last_eutran_plmn, &vsub->sgs.last_eutran_plmn,
+			sizeof(vsub->sgs.last_eutran_plmn));
+	}
+
 	return msc_a_ran_down(msc_a, MSC_ROLE_I, &msg);
 }
 
diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c
index 0645c54..daa5bc7 100644
--- a/src/libmsc/msc_a.c
+++ b/src/libmsc/msc_a.c
@@ -1648,8 +1648,13 @@
 		.msg_type = RAN_MSG_COMMON_ID,
 		.common_id = {
 			.imsi = vsub->imsi,
+			.last_eutran_plmn_present = vsub->sgs.last_eutran_plmn_present,
 		},
 	};
+	if (vsub->sgs.last_eutran_plmn_present) {
+		memcpy(&msg.common_id.last_eutran_plmn, &vsub->sgs.last_eutran_plmn,
+			sizeof(vsub->sgs.last_eutran_plmn));
+	}
 
 	return msc_a_ran_down(msc_a, to_role, &msg);
 }
diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c
index 2890076..4cce289 100644
--- a/src/libmsc/ran_msg_a.c
+++ b/src/libmsc/ran_msg_a.c
@@ -1218,7 +1218,11 @@
 		return ran_a_make_assignment_command(caller_fi, &ran_enc_msg->assignment_command);
 
 	case RAN_MSG_COMMON_ID:
-		return gsm0808_create_common_id(ran_enc_msg->common_id.imsi, NULL, NULL);
+		return gsm0808_create_common_id(ran_enc_msg->common_id.imsi, NULL,
+						ran_enc_msg->common_id.last_eutran_plmn_present ?
+							&ran_enc_msg->common_id.last_eutran_plmn :
+							NULL
+						);
 
 	case RAN_MSG_CIPHER_MODE_COMMAND:
 		return ran_a_make_cipher_mode_command(caller_fi, &ran_enc_msg->cipher_mode_command);
diff --git a/src/libmsc/sgs_iface.c b/src/libmsc/sgs_iface.c
index d13449d..04302ae 100644
--- a/src/libmsc/sgs_iface.c
+++ b/src/libmsc/sgs_iface.c
@@ -608,12 +608,14 @@
 	char *mme_name;
 	struct vlr_sgs_cfg vlr_sgs_cfg;
 	struct vlr_subscr *vsub;
+	struct osmo_plmn_id last_eutran_plmn_buf, *last_eutran_plmn = NULL;
 
 	/* Check for lingering connections */
 	vsub = vlr_subscr_find_by_imsi(gsm_network->vlr, imsi, __func__);
 	if (vsub) {
 		subscr_conn_toss(vsub);
 		vlr_subscr_put(vsub, __func__);
+		vsub = NULL;
 	}
 
 	/* Determine MME-Name */
@@ -639,11 +641,29 @@
 		return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_MISSING_MAND_IE, msg, SGSAP_IE_LAI);
 	gsm48_decode_lai2(gsm48_lai, &new_lai);
 
+	/* 3GPP TS 23.272 sec 4.3.3 (CSFB):
+	 * "During the SGs location update procedure, obtaining the last used LTE PLMN ID via TAI"
+	 */
+	if (TLVP_PRES_LEN(tp, SGSAP_IE_TAI, 3)) {
+		last_eutran_plmn = &last_eutran_plmn_buf;
+		osmo_plmn_from_bcd(TLVP_VAL(tp, SGSAP_IE_TAI), last_eutran_plmn);
+		/* TODO: we could also gather the TAC from here, but we don't need it yet */
+	} else if (TLVP_PRES_LEN(tp, SGSAP_IE_EUTRAN_CGI, 3)) {
+		/* Since TAI is optional, let's try harder getting Last Used
+		 * E-UTRAN PLMN ID by fetching it from E-UTRAN CGI */
+		last_eutran_plmn = &last_eutran_plmn_buf;
+		osmo_plmn_from_bcd(TLVP_VAL(tp, SGSAP_IE_EUTRAN_CGI), last_eutran_plmn);
+		/* TODO: we could also gather the ECI from here, but we don't need it yet */
+	} else {
+		LOGSGC(sgc, LOGL_INFO, "Receiving SGsAP-LOCATION-UPDATE-REQUEST without TAI nor "
+		       "E-CGI IEs, fast fallback GERAN->EUTRAN won't be possible!\n");
+	}
+
 	/* Perform actual location update */
 	memcpy(vlr_sgs_cfg.timer, sgc->sgs->cfg.timer, sizeof(vlr_sgs_cfg.timer));
 	memcpy(vlr_sgs_cfg.counter, sgc->sgs->cfg.counter, sizeof(vlr_sgs_cfg.counter));
 	rc = vlr_sgs_loc_update(gsm_network->vlr, &vlr_sgs_cfg, sgs_tx_loc_upd_resp_cb, sgs_iface_tx_paging,
-				sgs_tx_mm_info_cb, mme_name, type, imsi, &new_lai);
+				sgs_tx_mm_info_cb, mme_name, type, imsi, &new_lai, last_eutran_plmn);
 	if (rc != 0) {
 		resp = gsm29118_create_lu_rej(imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, NULL);
 		sgs_tx(sgc, resp);
@@ -905,6 +925,26 @@
 	if (!vsub)
 		return sgs_tx_status(sgc, imsi, SGSAP_SGS_CAUSE_IMSI_UNKNOWN, msg, SGSAP_IE_IMSI);
 
+	/* 3GPP TS 23.272 sec 4.3.3 (CSFB):
+	 * "During the SGs location update procedure, obtaining the last used LTE PLMN ID via TAI"
+	 */
+	vsub->sgs.last_eutran_plmn_present = TLVP_PRES_LEN(tp, SGSAP_IE_EUTRAN_CGI, 3);
+	if (TLVP_PRES_LEN(tp, SGSAP_IE_TAI, 3)) {
+		vsub->sgs.last_eutran_plmn_present = true;
+		osmo_plmn_from_bcd(TLVP_VAL(tp, SGSAP_IE_TAI), &vsub->sgs.last_eutran_plmn);
+		/* TODO: we could also gather the TAC from here, but we don't need it yet */
+	} else if (TLVP_PRES_LEN(tp, SGSAP_IE_EUTRAN_CGI, 3)) {
+		/* Since TAI is optional, let's try harder getting Last Used
+		 * E-UTRAN PLMN ID by fetching it from E-UTRAN CGI */
+		vsub->sgs.last_eutran_plmn_present = true;
+		osmo_plmn_from_bcd(TLVP_VAL(tp, SGSAP_IE_EUTRAN_CGI), &vsub->sgs.last_eutran_plmn);
+		/* TODO: we could also gather the ECI from here, but we don't need it yet */
+	} else if (!vsub->sgs.last_eutran_plmn_present) {
+		LOGSGC(sgc, LOGL_INFO, "Receiving SGsAP-MO-CSFB-INDICATION without TAI nor "
+		       "E-CGI IEs, and they are not known from previous SGsAP-LOCATION-UPDATE-REQUEST. "
+		       "Fast fallback GERAN->EUTRAN won't be possible!\n");
+	}
+
 	/* Check for lingering connections */
 	subscr_conn_toss(vsub);
 
diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c
index 33d6331..02aceef 100644
--- a/src/libvlr/vlr.c
+++ b/src/libvlr/vlr.c
@@ -476,6 +476,23 @@
 	       vsub->imsi, vsub->msisdn);
 }
 
+void vlr_subscr_set_last_used_eutran_plmn_id(struct vlr_subscr *vsub,
+					     const struct osmo_plmn_id *last_eutran_plmn)
+{
+	if (!vsub)
+		return;
+	if (last_eutran_plmn) {
+		vsub->sgs.last_eutran_plmn_present = true;
+		memcpy(&vsub->sgs.last_eutran_plmn, last_eutran_plmn, sizeof(*last_eutran_plmn));
+	} else {
+		vsub->sgs.last_eutran_plmn_present = false;
+	}
+	DEBUGP(DVLR, "set Last E-UTRAN PLMN ID on subscriber: %s\n",
+	       vsub->sgs.last_eutran_plmn_present ?
+	         osmo_plmn_name(&vsub->sgs.last_eutran_plmn) :
+		 "(none)");
+}
+
 bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi)
 {
 	return vsub && imsi && vsub->imsi[0] && !strcmp(vsub->imsi, imsi);
diff --git a/src/libvlr/vlr_sgs.c b/src/libvlr/vlr_sgs.c
index 269dda6..5659886 100644
--- a/src/libvlr/vlr_sgs.c
+++ b/src/libvlr/vlr_sgs.c
@@ -68,11 +68,12 @@
  * \param[in] type location update type (normal or IMSI attach).
  * \param[in] imsi mobile identity (IMSI).
  * \param[in] new_lai identifier of the new location area.
+ * \param[in] last_eutran_plnm_id Last E-UTRAN PLMN ID (can be NULL).
  * \returns 0 in case of success, -EINVAL in case of error. */
 int vlr_sgs_loc_update(struct vlr_instance *vlr, struct vlr_sgs_cfg *cfg,
 		       vlr_sgs_lu_response_cb_t response_cb, vlr_sgs_lu_paging_cb_t paging_cb,
 		       vlr_sgs_lu_mminfo_cb_t mminfo_cb, char *mme_name, enum vlr_lu_type type, const char *imsi,
-		       struct osmo_location_area_id *new_lai)
+		       struct osmo_location_area_id *new_lai, struct osmo_plmn_id *last_eutran_plmn)
 {
 	struct vlr_subscr *vsub = NULL;
 
@@ -93,6 +94,7 @@
 	vsub->sgs.paging_cb = paging_cb;
 	vsub->sgs.mminfo_cb = mminfo_cb;
 	vlr_subscr_set_imsi(vsub, imsi);
+	vlr_subscr_set_last_used_eutran_plmn_id(vsub, last_eutran_plmn);
 	osmo_strlcpy(vsub->sgs.mme_name, mme_name, sizeof(vsub->sgs.mme_name));
 
 	osmo_fsm_inst_dispatch(vsub->sgs_fsm, SGS_UE_E_RX_LU_FROM_MME, NULL);

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-msc/+/23915
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-msc
Gerrit-Branch: master
Gerrit-Change-Id: Ic5f175b179973d0a50d94f00e15f5a3e332605fc
Gerrit-Change-Number: 23915
Gerrit-PatchSet: 4
Gerrit-Owner: pespin <pespin at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210429/c7830df5/attachment.htm>


More information about the gerrit-log mailing list