aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2018-07-09 14:39:47 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2018-07-13 11:47:51 +0200
commita98fead4642ba0ecf7ab0e7862fb468d0ae911ad (patch)
tree48bd3989759581d8d486ace764511fdeec1c698f
parent80d407fc3f407898de3c62d6265665d08a830280 (diff)
Maintain per ggsn pdp ctx list
This way we can easily track all pdp context associated to a specific ggsn, which is useful to handle some scenarios, such as the one implemented in next commit, in which specs references that GSNs should ping only other GSNs with at least one pdp ctx in common. So the list of pdp ctx per GGSN is really useful too (and cheap computationally) to check if we should arm or disarm the echo procedure timer. So this commit can be seen as a preparation for next commit. Change-Id: I3bbcc0883df2bf1290ba8d4bd70db8baa494087a
-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 64e5619d..33b12dc2 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 688eaed1..a58e504c 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 70112cbf..2da8c4a7 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;
}