Move sgsn_pdp_ctx to its own file pdpctx.{c,h}

This further shrinks the mess in gprs_sgsn.h, and allows to easily see
layer violations (like pdpctx.c requiring llc.h)

Change-Id: Iad4da06efee7d8514ff48423bdaebc0f26413cc1
diff --git a/src/sgsn/gprs_sgsn.c b/src/sgsn/gprs_sgsn.c
index c911b6a..9d2ed7d 100644
--- a/src/sgsn/gprs_sgsn.c
+++ b/src/sgsn/gprs_sgsn.c
@@ -52,6 +52,7 @@
 #include <osmocom/sgsn/gprs_sndcp.h>
 #include <osmocom/sgsn/gtp_ggsn.h>
 #include <osmocom/sgsn/gtp.h>
+#include <osmocom/sgsn/pdpctx.h>
 
 #include <pdp.h>
 
@@ -64,7 +65,6 @@
 extern struct osmo_tdef sgsn_T_defs[];
 
 LLIST_HEAD(sgsn_mm_ctxts);
-LLIST_HEAD(sgsn_pdp_ctxts);
 
 const struct value_string sgsn_ran_type_names[] = {
 	{ MM_CTX_T_GERAN_Gb, "GPRS/EDGE via Gb" },
@@ -97,21 +97,6 @@
 	.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
 };
 
-static const struct rate_ctr_desc pdpctx_ctr_description[] = {
-	{ "udata:packets:in",	"User Data  Messages ( In)" },
-	{ "udata:packets:out",	"User Data  Messages (Out)" },
-	{ "udata:bytes:in",	"User Data  Bytes    ( In)" },
-	{ "udata:bytes:out",	"User Data  Bytes    (Out)" },
-};
-
-static const struct rate_ctr_group_desc pdpctx_ctrg_desc = {
-	.group_name_prefix = "sgsn:pdpctx",
-	.group_description = "SGSN PDP Context Statistics",
-	.num_ctr = ARRAY_SIZE(pdpctx_ctr_description),
-	.ctr_desc = pdpctx_ctr_description,
-	.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
-};
-
 static const struct rate_ctr_desc sgsn_ctr_description[] = {
 	{ "llc:dl_bytes", "Count sent LLC bytes before giving it to the bssgp layer" },
 	{ "llc:ul_bytes", "Count successful received LLC bytes (encrypt & fcs correct)" },
@@ -429,109 +414,6 @@
 	return NULL;
 }
 
-/* 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;
-
-	pdp = sgsn_pdp_ctx_by_nsapi(mm, nsapi);
-	if (pdp)
-		return NULL;
-
-	pdp = talloc_zero(tall_sgsn_ctx, struct sgsn_pdp_ctx);
-	if (!pdp)
-		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) {
-		LOGPDPCTXP(LOGL_ERROR, pdp, "Error allocation counter group\n");
-		talloc_free(pdp);
-		return NULL;
-	}
-	llist_add(&pdp->list, &mm->pdp_list);
-	sgsn_ggsn_ctx_add_pdp(pdp->ggsn, pdp);
-	llist_add(&pdp->g_list, &sgsn_pdp_ctxts);
-
-	return pdp;
-}
-
-/*
- * This function will not trigger any GSM DEACT PDP ACK messages, so you
- * probably want to call sgsn_delete_pdp_ctx() instead if the connection
- * isn't detached already.
- */
-void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp)
-{
-	struct sgsn_signal_data sig_data;
-
-	OSMO_ASSERT(pdp->mm != NULL);
-
-	/* There might still be pending callbacks in libgtp. So the parts of
-	 * this object relevant to GTP need to remain intact in this case. */
-
-	LOGPDPCTXP(LOGL_INFO, pdp, "Forcing release of PDP context\n");
-
-	if (pdp->mm->ran_type == MM_CTX_T_GERAN_Gb) {
-		/* Force the deactivation of the SNDCP layer */
-		if (pdp->mm->gb.llme)
-			sndcp_sm_deactivate_ind(&pdp->mm->gb.llme->lle[pdp->sapi], pdp->nsapi);
-	}
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pdp;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_TERMINATE, &sig_data);
-
-	/* Detach from MM context */
-	pdp_ctx_detach_mm_ctx(pdp);
-	if (pdp->ggsn)
-		sgsn_delete_pdp_ctx(pdp);
-}
-
-/*
- * Don't call this function directly unless you know what you are doing.
- * In normal conditions use sgsn_delete_pdp_ctx and in unspecified or
- * implementation dependent abnormal ones sgsn_pdp_ctx_terminate.
- */
-void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp)
-{
-	struct sgsn_signal_data sig_data;
-
-	memset(&sig_data, 0, sizeof(sig_data));
-	sig_data.pdp = pdp;
-	osmo_signal_dispatch(SS_SGSN, S_SGSN_PDP_FREE, &sig_data);
-
-	if (osmo_timer_pending(&pdp->timer)) {
-		LOGPDPCTXP(LOGL_ERROR, pdp, "Freeing PDP ctx with timer %u pending\n", pdp->T);
-		osmo_timer_del(&pdp->timer);
-	}
-
-	rate_ctr_group_free(pdp->ctrg);
-	if (pdp->mm)
-		llist_del(&pdp->list);
-	if (pdp->ggsn)
-		sgsn_ggsn_ctx_remove_pdp(pdp->ggsn, pdp);
-	llist_del(&pdp->g_list);
-
-	/* _if_ we still have a library handle, at least set it to NULL
-	 * to avoid any dereferences of the now-deleted PDP context from
-	 * sgsn_libgtp:cb_data_ind() */
-	if (pdp->lib) {
-		struct pdp_t *lib = pdp->lib;
-		LOGPDPCTXP(LOGL_NOTICE, pdp, "freeing PDP context that still "
-		     "has a libgtp handle attached to it, this shouldn't "
-		     "happen!\n");
-		osmo_generate_backtrace();
-		lib->priv = NULL;
-	}
-
-	talloc_free(pdp);
-}
-
 uint32_t sgsn_alloc_ptmsi(void)
 {
 	struct sgsn_mm_ctx *mm;