sm: Handle GMMSM-MODIFY.ind primitive
Change-Id: Ic765b7a565cac4abcf34d8c6868e103971d17822
This commit is contained in:
parent
70c6407f69
commit
f87b9da362
|
@ -156,6 +156,7 @@ int gprs_sm_prim_call_sndcp_up_cb(struct osmo_gprs_sndcp_prim *sndcp_prim);
|
|||
|
||||
struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_cnf(void);
|
||||
struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_ind(void);
|
||||
struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_deact_ind(void);
|
||||
|
||||
/* sm.c: */
|
||||
struct gprs_sm_ms *gprs_sm_ms_alloc(uint32_t ms_id);
|
||||
|
@ -167,9 +168,13 @@ struct gprs_sm_entity *gprs_sm_entity_alloc(struct gprs_sm_ms *ms, uint32_t nsap
|
|||
void gprs_sm_entity_free(struct gprs_sm_entity *sme);
|
||||
struct gprs_sm_entity *gprs_sm_find_sme_by_sess_id(uint32_t sess_id);
|
||||
|
||||
void gprs_sm_handle_ie_pdp_ctx_status(struct gprs_sm_ms *ms, const uint8_t *pdp_status);
|
||||
|
||||
int gprs_sm_submit_gmmsm_assign_req(const struct gprs_sm_entity *sme);
|
||||
int gprs_sm_submit_smreg_pdp_act_cnf(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause);
|
||||
int gprs_sm_submit_smreg_pdp_deact_ind(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause);
|
||||
int gprs_sm_submit_snsm_act_ind(const struct gprs_sm_entity *sme);
|
||||
int gprs_sm_submit_snsm_deact_ind(const struct gprs_sm_entity *sme);
|
||||
int gprs_sm_tx_act_pdp_ctx_req(struct gprs_sm_entity *sme);
|
||||
int gprs_sm_rx(struct gprs_sm_entity *sme, struct gsm48_hdr *gh, unsigned int len);
|
||||
|
||||
|
|
59
src/sm/sm.c
59
src/sm/sm.c
|
@ -236,6 +236,24 @@ int gprs_sm_submit_smreg_pdp_act_cnf(const struct gprs_sm_entity *sme, enum gsm4
|
|||
return rc;
|
||||
}
|
||||
|
||||
int gprs_sm_submit_smreg_pdp_deact_ind(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause)
|
||||
{
|
||||
struct osmo_gprs_sm_prim *sm_prim_tx;
|
||||
int rc;
|
||||
|
||||
sm_prim_tx = gprs_sm_prim_alloc_smreg_pdp_deact_ind();
|
||||
sm_prim_tx->smreg.ms_id = sme->ms->ms_id;
|
||||
sm_prim_tx->smreg.pdp_deact_ind.nsapi[0] = sme->nsapi;
|
||||
sm_prim_tx->smreg.pdp_deact_ind.num_nsapi = 1;
|
||||
sm_prim_tx->smreg.pdp_deact_ind.tear_down_ind = 0;
|
||||
sm_prim_tx->smreg.pdp_deact_ind.cause = cause;
|
||||
sm_prim_tx->smreg.pdp_deact_ind.pco_len = sme->pco_len;
|
||||
if (sme->pco_len)
|
||||
memcpy(sm_prim_tx->smreg.pdp_deact_cnf.pco, &sme->pco, sme->pco_len);
|
||||
|
||||
rc = gprs_sm_prim_call_up_cb(sm_prim_tx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int gprs_sm_submit_snsm_act_ind(const struct gprs_sm_entity *sme)
|
||||
{
|
||||
|
@ -253,6 +271,18 @@ int gprs_sm_submit_snsm_act_ind(const struct gprs_sm_entity *sme)
|
|||
return rc;
|
||||
}
|
||||
|
||||
int gprs_sm_submit_snsm_deact_ind(const struct gprs_sm_entity *sme)
|
||||
{
|
||||
struct osmo_gprs_sndcp_prim *sndcp_prim_tx;
|
||||
int rc;
|
||||
|
||||
sndcp_prim_tx = osmo_gprs_sndcp_prim_alloc_snsm_deactivate_ind(
|
||||
sme->ms->gmm.tlli, sme->nsapi);
|
||||
|
||||
rc = gprs_sm_prim_call_sndcp_up_cb(sndcp_prim_tx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Tx SM Activate PDP context request, 9.5.1 */
|
||||
int gprs_sm_tx_act_pdp_ctx_req(struct gprs_sm_entity *sme)
|
||||
{
|
||||
|
@ -431,3 +461,32 @@ int gprs_sm_rx(struct gprs_sm_entity *sme, struct gsm48_hdr *gh, unsigned int le
|
|||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void gprs_sm_handle_ie_pdp_ctx_status(struct gprs_sm_ms *ms, const uint8_t *pdp_status)
|
||||
{
|
||||
unsigned int i;
|
||||
/* 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. */
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ms->pdp); i++) {
|
||||
struct gprs_sm_entity *sme = ms->pdp[i];
|
||||
bool inactive;
|
||||
if (!sme)
|
||||
continue;
|
||||
|
||||
inactive = (sme->nsapi < 8) ?
|
||||
!(pdp_status[0] & (1 << sme->nsapi)) :
|
||||
!(pdp_status[1] & (1 << (sme->nsapi - 8)));
|
||||
if (!inactive)
|
||||
continue;
|
||||
LOGSME(sme, LOGL_NOTICE,
|
||||
"PDP context status informs PDP context is PDP-INACTIVE, deleting\n");
|
||||
gprs_sm_submit_snsm_deact_ind(sme);
|
||||
/* See TS 24.007 Appendix C.10: Wait for SNSM-DEACTIVATE.rsp,
|
||||
* then submit SMREG-DEACTIVATE.ind and free the object */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -187,6 +187,14 @@ struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_ind(void)
|
|||
return sm_prim;
|
||||
}
|
||||
|
||||
/* TS 24.007 6.5.1.7 SMREG-PDP-ACTIVATE-IND */
|
||||
struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_deact_ind(void)
|
||||
{
|
||||
struct osmo_gprs_sm_prim *sm_prim;
|
||||
sm_prim = sm_prim_smreg_alloc(OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, PRIM_OP_INDICATION, 0);
|
||||
return sm_prim;
|
||||
}
|
||||
|
||||
static int gprs_sm_prim_handle_unsupported(struct osmo_gprs_sm_prim *sm_prim)
|
||||
{
|
||||
LOGSM(LOGL_ERROR, "Unsupported sm_prim! %s\n", osmo_gprs_sm_prim_name(sm_prim));
|
||||
|
@ -339,7 +347,7 @@ int gprs_sm_prim_call_sndcp_up_cb(struct osmo_gprs_sndcp_prim *sndcp_prim)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* TS 24.007 6.6.1.1 SMREG-Attach.request:*/
|
||||
/* TS 24.007 5.1.2.20 SNSM-ACTIVATE.response: */
|
||||
static int gprs_sm_prim_handle_snsm_act_resp(struct osmo_gprs_sndcp_prim *sndcp_prim)
|
||||
{
|
||||
int rc;
|
||||
|
@ -365,6 +373,37 @@ static int gprs_sm_prim_handle_snsm_act_resp(struct osmo_gprs_sndcp_prim *sndcp_
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* TS 24.007 5.1.2.22 SNSM-DEACTIVATE.response: */
|
||||
static int gprs_sm_prim_handle_snsm_deact_resp(struct osmo_gprs_sndcp_prim *sndcp_prim)
|
||||
{
|
||||
int rc;
|
||||
struct gprs_sm_ms *ms;
|
||||
struct gprs_sm_entity *sme;
|
||||
|
||||
ms = gprs_sm_find_ms_by_tlli(sndcp_prim->snsm.tlli);
|
||||
if (!ms) {
|
||||
LOGSM(LOGL_ERROR, "Rx %s: Unable to find MS with TLLI=0x%08x\n",
|
||||
osmo_gprs_sndcp_prim_name(sndcp_prim), sndcp_prim->snsm.tlli);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sme = gprs_sm_ms_get_pdp_ctx(ms, sndcp_prim->snsm.activate_rsp.nsapi);
|
||||
if (!sme) {
|
||||
LOGMS(ms, LOGL_ERROR, "Rx %s: Unable to find NSAPI=%u\n",
|
||||
osmo_gprs_sndcp_prim_name(sndcp_prim),
|
||||
sndcp_prim->snsm.activate_rsp.nsapi);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
rc = gprs_sm_submit_smreg_pdp_deact_ind(sme, GSM_CAUSE_REACT_RQD);
|
||||
|
||||
/* Submitting GMM_RELEASE.ind received the GMM release was delayed until
|
||||
* getting SNSM-DEACT.ind->rsp pingpong, since it would free the sme. Do it now:
|
||||
*/
|
||||
rc = osmo_fsm_inst_dispatch(sme->ms_fsm.fi, GPRS_SM_MS_EV_GMM_RELEASE_IND, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* SNDCP higher layers push SNDCP primitive (SNSM) down to SM layer: */
|
||||
static int gprs_sm_prim_handle_sndcp_snsm(struct osmo_gprs_sndcp_prim *sndcp_prim)
|
||||
{
|
||||
|
@ -375,6 +414,8 @@ static int gprs_sm_prim_handle_sndcp_snsm(struct osmo_gprs_sndcp_prim *sndcp_pri
|
|||
rc = gprs_sm_prim_handle_snsm_act_resp(sndcp_prim);
|
||||
break;
|
||||
case OSMO_PRIM(OSMO_GPRS_SNDCP_SNSM_DEACTIVATE, PRIM_OP_RESPONSE):
|
||||
rc = gprs_sm_prim_handle_snsm_deact_resp(sndcp_prim);
|
||||
break;
|
||||
case OSMO_PRIM(OSMO_GPRS_SNDCP_SNSM_MODIFY, PRIM_OP_RESPONSE):
|
||||
case OSMO_PRIM(OSMO_GPRS_SNDCP_SNSM_STATUS, PRIM_OP_REQUEST):
|
||||
case OSMO_PRIM(OSMO_GPRS_SNDCP_SNSM_SEQUENCE, PRIM_OP_RESPONSE):
|
||||
|
@ -530,6 +571,42 @@ static int gprs_sm_prim_handle_gmmsm_unitdata_ind(struct osmo_gprs_gmm_prim *gmm
|
|||
return rc;
|
||||
}
|
||||
|
||||
/* Osmocom specific, GMMSM-MODIFY-IND */
|
||||
static int gprs_sm_prim_handle_gmmsm_modify_ind(struct osmo_gprs_gmm_prim *gmm_prim)
|
||||
{
|
||||
struct osmo_gprs_gmm_gmmsm_prim *gmmsm = &gmm_prim->gmmsm;
|
||||
struct gprs_sm_entity *sme;
|
||||
struct gprs_sm_ms *ms;
|
||||
int rc = 0;
|
||||
|
||||
sme = gprs_sm_find_sme_by_sess_id(gmmsm->sess_id);
|
||||
if (!sme) {
|
||||
LOGSM(LOGL_ERROR, "Rx GMMSM-MODIFY.ind for non existing SM Entity\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ms = sme->ms;
|
||||
|
||||
/* Update allocated PTMSI: */
|
||||
if (gmm_prim->gmmsm.modify_ind.allocated_ptmsi != GSM_RESERVED_TMSI)
|
||||
ms->gmm.ptmsi = gmm_prim->gmmsm.modify_ind.allocated_ptmsi;
|
||||
ms->gmm.ptmsi_sig = gmm_prim->gmmsm.modify_ind.allocated_ptmsi_sig;
|
||||
/* Update allocated TLLI: */
|
||||
ms->gmm.tlli = gmm_prim->gmmsm.modify_ind.allocated_tlli;
|
||||
/* Update the current RAI: */
|
||||
memcpy(&ms->gmm.ra, &gmm_prim->gmmsm.modify_ind.rai, sizeof(ms->gmm.ra));
|
||||
|
||||
if (gmm_prim->gmmsm.modify_ind.pdp_ctx_status_present)
|
||||
gprs_sm_handle_ie_pdp_ctx_status(ms, gmm_prim->gmmsm.modify_ind.pdp_ctx_status);
|
||||
/* Note: sme may be freed here, it needs to be looked up again:
|
||||
* sme = gprs_sm_find_sme_by_sess_id(gmmsm->sess_id);
|
||||
*/
|
||||
|
||||
/* TODO: Handle gmm_prim->gmmsm.modify_ind.rx_npdu_numbers_list
|
||||
* Submit SNSM-SEQUENCE-IND, see TS 24.007 "C.16(cont’d) Routing Area Update, Inter SGSN" */
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int gprs_sm_prim_handle_gmmsm(struct osmo_gprs_gmm_prim *gmm_prim)
|
||||
{
|
||||
int rc = 0;
|
||||
|
@ -543,6 +620,9 @@ static int gprs_sm_prim_handle_gmmsm(struct osmo_gprs_gmm_prim *gmm_prim)
|
|||
case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_INDICATION):
|
||||
rc = gprs_sm_prim_handle_gmmsm_unitdata_ind(gmm_prim);
|
||||
break;
|
||||
case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_MODIFY, PRIM_OP_INDICATION):
|
||||
rc = gprs_sm_prim_handle_gmmsm_modify_ind(gmm_prim);
|
||||
break;
|
||||
default:
|
||||
rc = gprs_sm_prim_handle_gmm_unsupported(gmm_prim);
|
||||
rc = 1;
|
||||
|
|
Loading…
Reference in New Issue