pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-gprs/+/32983 )
Change subject: llc: Implement LLGM-TRIGGER.req
......................................................................
llc: Implement LLGM-TRIGGER.req
Change-Id: Id1af5912f407fe055a59a4bb217936307697975f
---
M include/osmocom/gprs/llc/llc_prim.h
M include/osmocom/gprs/llc/llc_private.h
M src/llc/llc.c
M src/llc/llc_llgmm.c
4 files changed, 95 insertions(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/83/32983/1
diff --git a/include/osmocom/gprs/llc/llc_prim.h b/include/osmocom/gprs/llc/llc_prim.h
index 904e9fa..175ede4 100644
--- a/include/osmocom/gprs/llc/llc_prim.h
+++ b/include/osmocom/gprs/llc/llc_prim.h
@@ -88,6 +88,16 @@
return get_value_string(osmo_gprs_llc_bssgp_prim_type_names, val);
}
+/* TS 04.64 Section 7.2.1.3 LLGMM-TRIGGER */
+/* 3GPP TS 24.008 2.1.2 "Cell Notification" is considered a different trigger
+ * type than Cell Update since lower layers behave different (tx LLC NULL vs UI
+ * frame). Furthermore, the one knowing about requirement to use one or the other
+ * is the upper layer (GMM), as well as the one responsible of READY timer. */
+enum osmo_gprs_llc_llgm_trigger_type {
+ OSMO_GPRS_LLC_LLGM_TRIGGER_CELL_UPDATE,
+ OSMO_GPRS_LLC_LLGM_TRIGGER_CELL_NOTIFICATION,
+ OSMO_GPRS_LLC_LLGM_TRIGGER_PAGE_RESP,
+};
/* Parameters for OSMO_GPRS_LLC_LLGMM_* prims */
struct osmo_gprs_llc_llgmm_prim {
@@ -104,7 +114,7 @@
} assign_req;
/* OSMO_GPRS_LLC_LLGMM_TRIGGER | Req */
struct {
- uint8_t cause;
+ uint8_t cause; /* enum osmo_gprs_llc_llgm_trigger_type */
} trigger_req;
/* OSMO_GPRS_LLC_LLGMM_SUSPEND | Req */
struct {
diff --git a/include/osmocom/gprs/llc/llc_private.h
b/include/osmocom/gprs/llc/llc_private.h
index ed68c7b..78e6e9f 100644
--- a/include/osmocom/gprs/llc/llc_private.h
+++ b/include/osmocom/gprs/llc/llc_private.h
@@ -323,6 +323,7 @@
int gprs_llc_lle_tx_xid_req(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int
l3par_len);
int gprs_llc_lle_tx_xid_resp(struct gprs_llc_lle *lle, uint8_t *l3par, unsigned int
l3par_len);
int gprs_llc_lle_tx_ui(struct gprs_llc_lle *lle, uint8_t *l3_pdu, size_t l3_pdu_len, bool
encryptable);
+int gprs_llc_lle_tx_null(const struct gprs_llc_lle *lle);
/* llc_prim.c: */
struct osmo_gprs_llc_prim *gprs_llc_prim_alloc(enum osmo_gprs_llc_prim_sap sap, unsigned
int type,
diff --git a/src/llc/llc.c b/src/llc/llc.c
index 4be7a9a..e0c7a39 100644
--- a/src/llc/llc.c
+++ b/src/llc/llc.c
@@ -292,6 +292,39 @@
return 0;
}
+/* 6.4.1.7 NULL command */
+int gprs_llc_lle_tx_null(const struct gprs_llc_lle *lle)
+{
+ int rc;
+ struct msgb *msg;
+ struct gprs_llc_pdu_decoded pdu_dec = {
+ .sapi = lle->sapi,
+ .fmt = OSMO_GPRS_LLC_FMT_U,
+ .func = OSMO_GPRS_LLC_FUNC_NULL,
+ .flags = 0 /* P=0 */,
+ };
+ struct osmo_gprs_llc_prim *llc_prim;
+
+ /* LLC payload is put directly below: */
+ if (g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_SGSN)
+ llc_prim = gprs_llc_prim_alloc_bssgp_dl_unitdata_req(lle->llme->tlli, NULL, 0);
+ else
+ llc_prim = gprs_llc_prim_alloc_grr_unitdata_req(lle->llme->tlli, NULL, 0);
+ msg = llc_prim->oph.msg;
+ msg->l3h = msg->tail;
+
+ rc = gprs_llc_pdu_encode(msg, &pdu_dec);
+ if (rc < 0) {
+ LOGLLC(LOGL_NOTICE, "Failed to encode U DM\n");
+ msgb_free(msg);
+ return rc;
+ }
+
+ /* Send BSSGP-DL-UNITDATA.req (SGSN) / GRR-UNITDATA.req (MS) */
+ gprs_llc_prim_call_down_cb(llc_prim);
+ return 0;
+}
+
/* Transmit a UI frame over the given SAPI:
'encryptable' indicates whether particular message can be encrypted according
to 3GPP TS 24.008 § 4.7.1.2
diff --git a/src/llc/llc_llgmm.c b/src/llc/llc_llgmm.c
index 7b09a69..973b698 100644
--- a/src/llc/llc_llgmm.c
+++ b/src/llc/llc_llgmm.c
@@ -274,6 +274,46 @@
return rc;
}
+/* 7.2.1.3 LLGMM-TRIGGER.req (SGSN):*/
+static int llc_prim_handle_llgm_trigger_req(struct osmo_gprs_llc_prim *llc_prim)
+{
+ struct gprs_llc_lle *lle;
+ int rc;
+ struct gprs_llc_llme *llme = gprs_llc_find_llme_by_tlli(llc_prim->llgmm.tlli);
+
+ if (!llme) {
+ LOGLLC(LOGL_NOTICE, "Rx %s: Unknown TLLI 0x%08x\n",
+ osmo_gprs_llc_prim_name(llc_prim), llc_prim->llgmm.tlli);
+ rc = -ENOKEY;
+ goto ret_free;
+ }
+ LOGLLME(llme, LOGL_INFO, "%s\n", osmo_gprs_llc_prim_name(llc_prim));
+
+ lle = gprs_llc_llme_get_lle(llme, OSMO_GPRS_LLC_SAPI_GMM);
+
+ /* "If there is a frame waiting to be transmitted in the MS, then this
+ * frame shall be transmitted on the corresponding SAPI or optionally a
+ * UI frame with no information field shall be transmitted on any SAPI.
+ * Otherwise if Cause indicates Cell Update and if Cell Notification is
+ * indicated by the SGSN (see 3GPP TS 24.008 [8a]), then a NULL frame
+ * with P=0 shall be transmitted on any SAPI."
+ */
+ switch (llc_prim->llgmm.trigger_req.cause) {
+ case OSMO_GPRS_LLC_LLGM_TRIGGER_CELL_NOTIFICATION:
+ rc = gprs_llc_lle_tx_null(lle);
+ break;
+ case OSMO_GPRS_LLC_LLGM_TRIGGER_CELL_UPDATE:
+ case OSMO_GPRS_LLC_LLGM_TRIGGER_PAGE_RESP:
+ default:
+ rc = gprs_llc_lle_tx_ui(lle, NULL, 0, false);
+ break;
+ }
+
+ret_free:
+ msgb_free(llc_prim->oph.msg);
+ return rc;
+}
+
/* 7.2.1.4 LLGMM-SUSPEND.req (MS/SGSN):*/
static int llc_prim_handle_llgm_suspend_req(struct osmo_gprs_llc_prim *llc_prim)
{
@@ -332,7 +372,7 @@
break;
case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_TRIGGER, PRIM_OP_REQUEST):
OSMO_ASSERT(g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_MS);
- rc = gprs_llc_prim_handle_unsupported(llc_prim);
+ rc = llc_prim_handle_llgm_trigger_req(llc_prim);
break;
case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_SUSPEND, PRIM_OP_REQUEST):
OSMO_ASSERT(g_llc_ctx->location == OSMO_GPRS_LLC_LOCATION_MS ||
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-gprs/+/32983
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: Id1af5912f407fe055a59a4bb217936307697975f
Gerrit-Change-Number: 32983
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newchange