laforge has submitted this change. ( 
https://gerrit.osmocom.org/c/osmo-sgsn/+/39241?usp=email )

Change subject: GMM: rework PDP context status
......................................................................

GMM: rework PDP context status

Use an uint16 instead of an pointer with an unknown length.
Also encode the current active PDP context (e.g. on 2G/4G
mobilty this could change). It resynchronizes the UE with the SGSN
state.

Change-Id: I12d3110c9365132f96ef7ff8a1be22a431682c81
---
M src/sgsn/gprs_gmm.c
M tests/sgsn/sgsn_test.c
2 files changed, 77 insertions(+), 55 deletions(-)

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




diff --git a/src/sgsn/gprs_gmm.c b/src/sgsn/gprs_gmm.c
index 6122421..357b762 100644
--- a/src/sgsn/gprs_gmm.c
+++ b/src/sgsn/gprs_gmm.c
@@ -196,6 +196,61 @@
        sgsn_mm_ctx_cleanup_free(ctx);
 }

+
+/* 3GPP TS 24.008 § 10.5.7.1 Process PDP context status value, bit 0 
corresponds to nsapi 0 */
+static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
+                                 uint16_t pdp_status)
+{
+       struct sgsn_pdp_ctx *pdp, *pdp2;
+       /* 24.008 4.7.5.1.3: If the PDP context status information element is
+        * included in ROUTING AREA UPDATE REQUEST message, then the network
+        * shall deactivate all those PDP contexts locally (without peer to
+        * peer signalling between the MS and the network), which are not in SM
+        * state PDP-INACTIVE on network side but are indicated by the MS as
+        * being in state PDP-INACTIVE. */
+
+       /* NSAPI 0 - 4 are spare, ignore these */
+       pdp_status &= 0xffe0;
+
+       llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
+               bool active = (pdp_status & (1 << pdp->nsapi));
+               if (active)
+                       continue;
+
+               LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for 
NSAPI=%u "
+                                             "due to PDP CTX STATUS 
IE=0x%02x\n",
+                         pdp->nsapi, pdp_status);
+               pdp->ue_pdp_active = false;
+               if (pdp->ggsn)
+                       sgsn_delete_pdp_ctx(pdp);
+               else /* GTP side already detached, freeing */
+                       sgsn_pdp_ctx_free(pdp);
+       }
+}
+
+/* 3GPP TS 24.008 § 10.5.7.1 Encode PDP context status value, bit 0 correspond 
to nsapi 0 */
+uint16_t encode_ms_ctx_status(struct sgsn_mm_ctx *mmctx)
+{
+       struct sgsn_pdp_ctx *pdp;
+
+       uint16_t pdp_status = 0;
+
+       llist_for_each_entry(pdp, &mmctx->pdp_list, list) {
+               if (pdp->ue_pdp_active)
+                       pdp_status |= (1 << pdp->nsapi);
+       }
+
+       return pdp_status;
+}
+
+/* 3GPP TS 24.008 § 4.7.13.4/10.5.7.1 Service request procedure not accepted 
by the
+ * network. Returns true if MS has active PDP contexts in pdp_status */
+bool pdp_status_has_active_nsapis(uint16_t pdp_status)
+{
+       /* NSAPI 0 - 4 are spare and should be ignored 0 */
+       return (pdp_status >> 5) != 0;
+}
+
 /* Chapter 9.4.18 */
 static int _tx_status(struct msgb *msg, uint8_t cause,
                      struct sgsn_mm_ctx *mmctx)
@@ -1487,6 +1542,8 @@
        rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
        rua->force_stby = 0;    /* not indicated */
        rua->upd_result = 0;    /* RA updated */
+
+       /* Periodic RA update timer */
        t = osmo_tdef_get(sgsn->cfg.T_defs, 3312, OSMO_TDEF_S, -1);
        rua->ra_upd_timer = gprs_secs_to_tmr_floor(t);

@@ -1515,12 +1572,19 @@
        }
        *l = rc;
 #endif
+       /* MS identity */
+       /* List of Received N-PDU */

        /* Optional: Negotiated READY timer value */
        t = osmo_tdef_get(sgsn->cfg.T_defs, 3314, OSMO_TDEF_S, -1);
        msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY, gprs_secs_to_tmr_floor(t));

-       /* Option: MS ID, ... */
+       /* GMM cause */
+       /* PDP Context Status */
+       uint16_t pdp_ctx_status = encode_ms_ctx_status(mm);
+       msgb_tlv_put(msg, GSM48_IE_GMM_PDP_CTX_STATUS, 2, (uint8_t *) 
&pdp_ctx_status);
+
+       /* MS ID, ... */
        return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }

@@ -1545,48 +1609,6 @@
        return gsm48_gmm_sendmsg(msg, 0, NULL, false);
 }

-static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
-                                 const uint8_t *pdp_status)
-{
-       struct sgsn_pdp_ctx *pdp, *pdp2;
-       /* 24.008 4.7.5.1.3: If the PDP context status information element is
-        * included in ROUTING AREA UPDATE REQUEST message, then the network
-        * shall deactivate all those PDP contexts locally (without peer to
-        * peer signalling between the MS and the network), which are not in SM
-        * state PDP-INACTIVE on network side but are indicated by the MS as
-        * being in state PDP-INACTIVE. */
-
-       llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
-               bool inactive = (pdp->nsapi < 8) ?
-                                       !(pdp_status[0] & (1 << pdp->nsapi)) :
-                                       !(pdp_status[1] & (1 << (pdp->nsapi - 
8)));
-               if (!inactive)
-                       continue;
-
-               LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for 
NSAPI=%u "
-                       "due to PDP CTX STATUS IE=0x%02x%02x\n",
-                       pdp->nsapi, pdp_status[1], pdp_status[0]);
-               pdp->ue_pdp_active = false;
-               if (pdp->ggsn)
-                       sgsn_delete_pdp_ctx(pdp);
-               else /* GTP side already detached, freeing */
-                       sgsn_pdp_ctx_free(pdp);
-       }
-}
-
-/* 3GPP TS 24.008 § 4.7.13.4 Service request procedure not accepted by the
- * network. Returns true if MS has active PDP contexts in pdp_status */
-bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t 
pdp_status_len)
-{
-       size_t i;
-
-       for (i = 0; i < pdp_status_len; i++)
-               if (pdp_status[i] != 0)
-                       return true;
-
-       return false;
-}
-
 /* Chapter 9.4.14: Routing area update request */
 static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
                                   struct gprs_llc_llme *llme)
@@ -1777,7 +1799,7 @@
        /* Look at PDP Context Status IE and see if MS's view of
         * activated/deactivated NSAPIs agrees with our view */
        if (TLVP_PRESENT(&req.tlv, GSM48_IE_GMM_PDP_CTX_STATUS)) {
-               const uint8_t *pdp_status = TLVP_VAL(&req.tlv, 
GSM48_IE_GMM_PDP_CTX_STATUS);
+               uint16_t pdp_status = osmo_load16le(TLVP_VAL(&req.tlv, 
GSM48_IE_GMM_PDP_CTX_STATUS));
                process_ms_ctx_status(mmctx, pdp_status);
        }

@@ -1936,8 +1958,7 @@
        /* 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);
-               const size_t pdp_status_len = TLVP_LEN(&tp, 
GSM48_IE_GMM_PDP_CTX_STATUS);
+               uint16_t pdp_status =  tlvp_val16be(&tp, 
GSM48_IE_GMM_PDP_CTX_STATUS);

                process_ms_ctx_status(ctx, pdp_status);

@@ -1946,7 +1967,7 @@
                 * Active state in pdp_status but there is no PDP contexts on
                 * SGSN side then Reject with the cause will force the mobile to
                 * reset PDP contexts */
-               if (llist_empty(&ctx->pdp_list) && 
pdp_status_has_active_nsapis(pdp_status, pdp_status_len)) {
+               if (llist_empty(&ctx->pdp_list) && 
pdp_status_has_active_nsapis(pdp_status)) {
                        reject_cause = GMM_CAUSE_NO_PDP_ACTIVATED;
                        goto rejected;
                }
diff --git a/tests/sgsn/sgsn_test.c b/tests/sgsn/sgsn_test.c
index 29dad74..6dcda84 100644
--- a/tests/sgsn/sgsn_test.c
+++ b/tests/sgsn/sgsn_test.c
@@ -1582,20 +1582,21 @@
        cleanup_test();
 }

-bool pdp_status_has_active_nsapis(const uint8_t *pdp_status, const size_t 
pdp_status_len);
+bool pdp_status_has_active_nsapis(uint16_t pdp_status);

 static void test_pdp_status_has_active_nsapis(void)
 {
-       const size_t pdp_status_len = 2;
-       const uint8_t pdp_status1[] = { 0b00100000, 0b00000000 }; /* PDP NSAPI 
5 active */
-       const uint8_t pdp_status2[] = { 0b00000000, 0b00000000 }; /* no active 
PDP NSAPI */
-       const uint8_t pdp_status3[] = { 0b00000000, 0b00000001 }; /* PDP NSAPI 
8 active */
+       uint16_t pdp_status1 = 0b0000000000100000; /* PDP NSAPI 5 active */
+       uint16_t pdp_status2 = 0b0000000000000000; /* no active PDP NSAPI */
+       uint16_t pdp_status3 = 0b0000000100000000; /* PDP NSAPI 8 active */
+       uint16_t pdp_status4 = 0b0000000000000001; /* reserved NSAPI 0 active 
-> no active */

        printf("Testing pdp_status_has_active_nsapis\n");

-       OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1, pdp_status_len));
-       OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2, pdp_status_len));
-       OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3, pdp_status_len));
+       OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status1));
+       OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status2));
+       OSMO_ASSERT(pdp_status_has_active_nsapis(pdp_status3));
+       OSMO_ASSERT(!pdp_status_has_active_nsapis(pdp_status4));
 }

 static struct log_info_cat gprs_categories[] = {

--
To view, visit https://gerrit.osmocom.org/c/osmo-sgsn/+/39241?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: osmo-sgsn
Gerrit-Branch: master
Gerrit-Change-Id: I12d3110c9365132f96ef7ff8a1be22a431682c81
Gerrit-Change-Number: 39241
Gerrit-PatchSet: 3
Gerrit-Owner: lynxis lazus <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>

Reply via email to