[PATCH] openbsc[master]: IuPS: add GMM Service Request rx and tx

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Neels Hofmeyr gerrit-no-reply at lists.osmocom.org
Mon Aug 22 12:36:07 UTC 2016


Review at  https://gerrit.osmocom.org/737

IuPS: add GMM Service Request rx and tx

Change-Id: Ib935de22d23a15f449927840d4d59497ce22abbd
---
M openbsc/src/gprs/gprs_gmm.c
1 file changed, 199 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/37/737/1

diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index aac3d86..3812516 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -688,6 +688,75 @@
 	strncpy(&ctx->hlr[0], called.number, sizeof(ctx->hlr) - 1);
 }
 
+#ifdef BUILD_IU
+/* Chapter 9.4.21: Service accept */
+static int gsm48_tx_gmm_service_ack(struct sgsn_mm_ctx *mm)
+{
+	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE ACK");
+	struct gsm48_hdr *gh;
+
+	LOGMMCTXP(LOGL_INFO, mm, "<- GPRS SERVICE ACCEPT (P-TMSI=0x%08x)\n", mm->p_tmsi);
+
+	mmctx2msgid(msg, mm);
+
+	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+	gh->proto_discr = GSM48_PDISC_MM_GPRS;
+	gh->msg_type = GSM48_MT_GMM_SERVICE_ACK;
+
+	/* Optional: PDP context status */
+	/* Optional: MBMS context status */
+
+	return gsm48_gmm_sendmsg(msg, 0, mm, false);
+}
+#endif
+
+/* Chapter 9.4.22: Service reject */
+static int _tx_gmm_service_rej(struct msgb *msg, uint8_t gmm_cause,
+			   const struct sgsn_mm_ctx *mm)
+{
+	struct gsm48_hdr *gh;
+
+	LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS SERVICE REJECT: %s\n",
+		  get_value_string(gsm48_gmm_cause_names, gmm_cause));
+
+	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
+	gh->proto_discr = GSM48_PDISC_MM_GPRS;
+	gh->msg_type = GSM48_MT_GMM_SERVICE_REJ;
+	gh->data[0] = gmm_cause;
+
+	return gsm48_gmm_sendmsg(msg, 0, NULL, true);
+}
+static int gsm48_tx_gmm_service_rej_oldmsg(const struct msgb *old_msg,
+					uint8_t gmm_cause)
+{
+	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ OLD");
+	gmm_copy_id(msg, old_msg);
+	return _tx_gmm_service_rej(msg, gmm_cause, NULL);
+}
+#if 0
+-- currently unused --
+static int gsm48_tx_gmm_service_rej(struct sgsn_mm_ctx *mm,
+				uint8_t gmm_cause)
+{
+	struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ");
+	mmctx2msgid(msg, mm);
+	return _tx_gmm_service_rej(msg, gmm_cause, mm);
+}
+#endif
+
+static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm);
+
+#ifdef BUILD_IU
+void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)
+{
+	/* Send RAB activation requests for all PDP contexts */
+	struct sgsn_pdp_ctx *pdp;
+	llist_for_each_entry(pdp, &ctx->pdp_list, list) {
+		iu_rab_act_ps(pdp->nsapi, pdp, 1);
+	}
+}
+#endif
+
 /* Check if we can already authorize a subscriber */
 static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
 {
@@ -776,6 +845,23 @@
 #endif
 
 		return gsm48_tx_gmm_att_ack(ctx);
+#ifdef BUILD_IU
+	case GSM48_MT_GMM_SERVICE_REQ:
+		/* TODO: PMM State transition */
+		ctx->pending_req = 0;
+		rc = gsm48_tx_gmm_service_ack(ctx);
+
+		if (ctx->iu.service.type == 1) {
+			activate_pdp_rabs(ctx);
+		}
+
+		return rc;
+#endif
+	case GSM48_MT_GMM_RA_UPD_REQ:
+		ctx->pending_req = 0;
+		/* Send RA UPDATE ACCEPT */
+		return gsm48_tx_gmm_ra_upd_ack(ctx);
+
 	default:
 		LOGMMCTXP(LOGL_ERROR, ctx,
 			  "only Attach Request is supported yet, "
@@ -1467,6 +1553,116 @@
 	return rc;
 }
 
+/* 3GPP TS 24.008 Section 9.4.20 Service request.
+ * In Iu, a UE in PMM-IDLE mode can use GSM48_MT_GMM_SERVICE_REQ to switch back
+ * to PMM-CONNECTED mode. */
+static int gsm48_rx_gmm_service_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
+{
+	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
+	uint8_t *cur = gh->data, *mi;
+	uint8_t ciph_seq_nr, service_type, mi_len, mi_type;
+	uint32_t tmsi;
+	struct tlv_parsed tp;
+	char mi_string[GSM48_MI_SIZE];
+	enum gsm48_gmm_cause reject_cause;
+	int rc;
+
+	LOGMMCTXP(LOGL_INFO, ctx, "-> GMM SERVICE REQUEST ");
+
+	/* This message is only valid in Iu mode */
+	if (!msg->dst) {
+		LOGPC(DMM, LOGL_INFO, "Invalid if not in Iu mode\n");
+		return -1;
+	}
+
+	/* Skip Ciphering key sequence number 10.5.1.2 */
+	ciph_seq_nr = *cur & 0x07;
+
+	/* Service type 10.5.5.20 */
+	service_type = (*cur++ >> 4) & 0x07;
+
+	/* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
+	mi_len = *cur++;
+	mi = cur;
+	if (mi_len > 8)
+		goto err_inval;
+	mi_type = *mi & GSM_MI_TYPE_MASK;
+	cur += mi_len;
+
+	gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
+
+	DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
+		get_value_string(gprs_service_t_strs, service_type));
+
+	LOGPC(DMM, LOGL_INFO, "\n");
+
+	/* Optional: PDP context status, MBMS context status, Uplink data status, Device properties */
+	tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur, (msg->data + msg->len) - cur, 0, 0);
+
+	switch (mi_type) {
+	case GSM_MI_TYPE_IMSI:
+		/* Try to find MM context based on IMSI */
+		if (!ctx)
+			ctx = sgsn_mm_ctx_by_imsi(mi_string);
+		if (!ctx) {
+			/* FIXME: We need to have a context for service request? */
+			reject_cause = GMM_CAUSE_NET_FAIL;
+			goto rejected;
+		}
+		msgid2mmctx(ctx, msg);
+		break;
+	case GSM_MI_TYPE_TMSI:
+		memcpy(&tmsi, mi+1, 4);
+		tmsi = ntohl(tmsi);
+		/* Try to find MM context based on P-TMSI */
+		if (!ctx)
+			ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
+		if (!ctx) {
+			/* FIXME: We need to have a context for service request? */
+			reject_cause = GMM_CAUSE_NET_FAIL;
+			goto rejected;
+		}
+		msgid2mmctx(ctx, msg);
+		break;
+	default:
+		LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting SERVICE REQUEST with "
+			"MI type %s\n", gsm48_mi_type_name(mi_type));
+		reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
+		goto rejected;
+	}
+
+	ctx->mm_state = GMM_COMMON_PROC_INIT;
+
+	ctx->iu.service.type = service_type;
+
+	/* TODO: Handle those only in case of accept? */
+	/* Look at PDP Context Status IE and see if MS's view of
+	 * activated/deactivated NSAPIs agrees with our view */
+	if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
+		const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
+		process_ms_ctx_status(ctx, pdp_status);
+	}
+
+
+	ctx->pending_req = GSM48_MT_GMM_SERVICE_REQ;
+	return gsm48_gmm_authorize(ctx);
+
+err_inval:
+	LOGPC(DMM, LOGL_INFO, "\n");
+	reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
+
+rejected:
+	/* Send SERVICE REJECT */
+	LOGMMCTXP(LOGL_NOTICE, ctx,
+		  "Rejecting Service Request with cause '%s' (%d)\n",
+		  get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
+	rc = gsm48_tx_gmm_service_rej_oldmsg(msg, reject_cause);
+
+	return rc;
+
+}
+
+
 static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
 {
 	struct gsm48_hdr *gh = msgb_l3(msg);
@@ -1545,6 +1741,9 @@
 	case GSM48_MT_GMM_ATTACH_REQ:
 		rc = gsm48_rx_gmm_att_req(mmctx, msg, llme);
 		break;
+	case GSM48_MT_GMM_SERVICE_REQ:
+		rc = gsm48_rx_gmm_service_req(mmctx, msg);
+		break;
 	/* For all the following types mmctx can not be NULL */
 	case GSM48_MT_GMM_ID_RESP:
 		if (!mmctx)

-- 
To view, visit https://gerrit.osmocom.org/737
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib935de22d23a15f449927840d4d59497ce22abbd
Gerrit-PatchSet: 1
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Neels Hofmeyr <nhofmeyr at sysmocom.de>



More information about the gerrit-log mailing list