aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-07-13 16:37:22 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2018-07-16 15:17:06 +0200
commita733a50931c4836fbda30f40d853bfab98441e98 (patch)
treed66e1207d8b180116753428a164c1edf490d6fe5
parent89895b027d57d2352afb56bdfef72c3e106168d6 (diff)
sgsn: Don't attempt to delete GTP pdp ctx if GGSN was restarted
Scenario and behaviour before this commit: - Received Echo Reply from GGSN has incremented RestartCounter - func sgsn_ggsn_ctx_drop_all_pdp() is called to dettach all pdp ctx from GGSN and request the MS to deact all related ctx. - DEACT ACCEPT is received from MS, and then it tries to send DEL PDP CTX to GGSN, expecting to receive a Confirmation and only then freeing the pdp ctx. The problem is that since the initial cause of triggering was a GGSN restart, the GGSN doesn't know anything about that pdp ctx anymore, so it's not useful sending it. We can instead dettach the GGSN and libgtp ref at drop_all_pdp() time and then when we receive DEACT ACCEPT from MS we can free the pdp ctx directly. Change-Id: I1c74098e181552c218e152bf4ac5035cea770428
-rw-r--r--src/gprs/gprs_gmm.c11
-rw-r--r--src/gprs/gprs_sgsn.c17
2 files changed, 21 insertions, 7 deletions
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index d06fa6c4d..ad56c6083 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -2699,7 +2699,11 @@ static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
}
/* stop timer 3395 */
pdpctx_timer_stop(pdp, 3395);
- return sgsn_delete_pdp_ctx(pdp);
+ if (pdp->ggsn)
+ return sgsn_delete_pdp_ctx(pdp);
+ /* GTP side already detached, freeing */
+ sgsn_pdp_ctx_free(pdp);
+ return 0;
}
static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
@@ -2723,7 +2727,10 @@ static void pdpctx_timer_cb(void *_pdp)
if (pdp->num_T_exp >= 4) {
LOGPDPCTXP(LOGL_NOTICE, pdp, "T3395 expired >= 5 times\n");
pdp->state = PDP_STATE_INACTIVE;
- sgsn_delete_pdp_ctx(pdp);
+ if (pdp->ggsn)
+ sgsn_delete_pdp_ctx(pdp);
+ else
+ sgsn_pdp_ctx_free(pdp);
break;
}
gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL, true);
diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c
index 35479fb02..ef0cc23da 100644
--- a/src/gprs/gprs_sgsn.c
+++ b/src/gprs/gprs_sgsn.c
@@ -444,7 +444,8 @@ void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
/* Detach from MM context */
pdp_ctx_detach_mm_ctx(pdp);
- sgsn_delete_pdp_ctx(pdp);
+ if (pdp->ggsn)
+ sgsn_delete_pdp_ctx(pdp);
}
/*
@@ -479,8 +480,6 @@ void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
lib->priv = NULL;
}
- if (pdp->destroy_ggsn)
- sgsn_ggsn_ctx_free(pdp->ggsn);
talloc_free(pdp);
}
@@ -702,9 +701,10 @@ failed:
static void drop_one_pdp(struct sgsn_pdp_ctx *pdp)
{
- if (pdp->mm->gmm_state == GMM_REGISTERED_NORMAL)
+ if (pdp->mm->gmm_state == GMM_REGISTERED_NORMAL) {
gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL, true);
- else {
+ sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
+ } else {
/* FIXME: GPRS paging in case MS is SUSPENDED */
LOGPDPCTXP(LOGL_NOTICE, pdp, "Hard-dropping PDP ctx due to GGSN "
"recovery\n");
@@ -739,6 +739,13 @@ void sgsn_ggsn_ctx_remove_pdp(struct sgsn_ggsn_ctx *ggc, struct sgsn_pdp_ctx *pd
llist_del(&pdp->ggsn_list);
if (llist_empty(&ggc->pdp_list) && osmo_timer_pending(&ggc->echo_timer))
osmo_timer_del(&ggc->echo_timer);
+ if (pdp->destroy_ggsn)
+ sgsn_ggsn_ctx_free(pdp->ggsn);
+ pdp->ggsn = NULL;
+ /* Drop references to libgtp since the conn is down */
+ if (pdp->lib)
+ pdp_freepdp(pdp->lib);
+ pdp->lib = NULL;
}
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)