aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/sgsn/gprs_sgsn.h8
-rw-r--r--src/gprs/gprs_sgsn.c22
-rw-r--r--src/gprs/sgsn_libgtp.c5
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;
}