diff options
-rw-r--r-- | include/osmocom/sgsn/gprs_sgsn.h | 8 | ||||
-rw-r--r-- | src/gprs/gprs_sgsn.c | 22 | ||||
-rw-r--r-- | src/gprs/sgsn_libgtp.c | 5 |
3 files changed, 18 insertions, 17 deletions
diff --git a/include/osmocom/sgsn/gprs_sgsn.h b/include/osmocom/sgsn/gprs_sgsn.h index 64e5619d6..33b12dc25 100644 --- a/include/osmocom/sgsn/gprs_sgsn.h +++ b/include/osmocom/sgsn/gprs_sgsn.h @@ -296,6 +296,7 @@ struct sgsn_pdp_ctx { struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */ int destroy_ggsn; /* destroy it on destruction */ struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */ + struct llist_head ggsn_list; /* list_head for ggsn->pdp_list */ struct rate_ctr_group *ctrg; //unsigned int id; @@ -338,6 +339,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm, uint8_t tid); struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm, + struct sgsn_ggsn_ctx *ggsn, uint8_t nsapi); void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp); void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp); @@ -350,12 +352,14 @@ struct sgsn_ggsn_ctx { struct in_addr remote_addr; int remote_restart_ctr; struct gsn_t *gsn; + struct llist_head pdp_list; /* list of associated pdp ctx (struct sgsn_pdp_ctx*) */ }; struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id); void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc); struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id); struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr); struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id); +int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn); struct apn_ctx { struct llist_head list; @@ -378,10 +382,6 @@ extern struct llist_head sgsn_pdp_ctxts; uint32_t sgsn_alloc_ptmsi(void); void sgsn_inst_init(void); -/* High-level function to be called in case a GGSN has disappeared or - * ottherwise lost state (recovery procedure) */ -int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn); - char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len); /* diff --git a/src/gprs/gprs_sgsn.c b/src/gprs/gprs_sgsn.c index 688eaed18..a58e504c5 100644 --- a/src/gprs/gprs_sgsn.c +++ b/src/gprs/gprs_sgsn.c @@ -388,6 +388,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm, /* you don't want to use this directly, call sgsn_create_pdp_ctx() */ struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm, + struct sgsn_ggsn_ctx *ggsn, uint8_t nsapi) { struct sgsn_pdp_ctx *pdp; @@ -401,6 +402,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm, return NULL; pdp->mm = mm; + pdp->ggsn = ggsn; pdp->nsapi = nsapi; pdp->ctrg = rate_ctr_group_alloc(pdp, &pdpctx_ctrg_desc, nsapi); if (!pdp->ctrg) { @@ -409,6 +411,7 @@ struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm, return NULL; } llist_add(&pdp->list, &mm->pdp_list); + llist_add(&pdp->ggsn_list, &ggsn->pdp_list); llist_add(&pdp->g_list, &sgsn_pdp_ctxts); return pdp; @@ -462,6 +465,8 @@ void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp) rate_ctr_group_free(pdp->ctrg); if (pdp->mm) llist_del(&pdp->list); + if (pdp->ggsn) + llist_del(&pdp->ggsn_list); llist_del(&pdp->g_list); /* _if_ we still have a library handle, at least set it to NULL @@ -496,6 +501,7 @@ struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id) ggc->remote_restart_ctr = -1; /* if we are called from config file parse, this gsn doesn't exist yet */ ggc->gsn = sgsn->gsn; + INIT_LLIST_HEAD(&ggc->pdp_list); llist_add(&ggc->list, &sgsn_ggsn_ctxts); return ggc; @@ -503,6 +509,7 @@ struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id) void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc) { + OSMO_ASSERT(llist_empty(&ggc->pdp_list)); llist_del(&ggc->list); talloc_free(ggc); } @@ -702,19 +709,14 @@ static void drop_one_pdp(struct sgsn_pdp_ctx *pdp) /* High-level function to be called in case a GGSN has disappeared or * otherwise lost state (recovery procedure) */ -int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn) +int sgsn_ggsn_ctx_drop_all_pdp(struct sgsn_ggsn_ctx *ggsn) { - struct sgsn_mm_ctx *mm; int num = 0; - llist_for_each_entry(mm, &sgsn_mm_ctxts, list) { - struct sgsn_pdp_ctx *pdp; - llist_for_each_entry(pdp, &mm->pdp_list, list) { - if (pdp->ggsn == ggsn) { - drop_one_pdp(pdp); - num++; - } - } + struct sgsn_pdp_ctx *pdp, *pdp2; + llist_for_each_entry_safe(pdp, pdp2, &ggsn->pdp_list, ggsn_list) { + drop_one_pdp(pdp); + num++; } return num; diff --git a/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c index 70112cbfd..2da8c4a74 100644 --- a/src/gprs/sgsn_libgtp.c +++ b/src/gprs/sgsn_libgtp.c @@ -145,7 +145,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, const uint8_t *qos; int rc; - pctx = sgsn_pdp_ctx_alloc(mmctx, nsapi); + pctx = sgsn_pdp_ctx_alloc(mmctx, ggsn, nsapi); if (!pctx) { LOGP(DGPRS, LOGL_ERROR, "Couldn't allocate PDP Ctx\n"); return NULL; @@ -160,7 +160,6 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, } pdp->priv = pctx; pctx->lib = pdp; - pctx->ggsn = ggsn; //pdp->peer = /* sockaddr_in of GGSN (receive) */ //pdp->ipif = /* not used by library */ @@ -603,7 +602,7 @@ static int cb_recovery(struct sockaddr_in *peer, uint8_t recovery) "releasing all PDP contexts\n", ggsn->remote_restart_ctr, recovery); ggsn->remote_restart_ctr = recovery; - drop_all_pdp_for_ggsn(ggsn); + sgsn_ggsn_ctx_drop_all_pdp(ggsn); } return 0; } |