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[] = {