Change in osmo-ggsn[master]: gtp: Add new API to avoid freeing pdp contexts during DEL CTX REQ

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Sat Jul 21 17:22:54 UTC 2018


Harald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/10006 )

Change subject: gtp: Add new API to avoid freeing pdp contexts during DEL CTX REQ
......................................................................

gtp: Add new API to avoid freeing pdp contexts during DEL CTX REQ

With this API, user is expectd to free the PDP ctx when the confirmation
for the release has been received (cb_conf time). This way user can
maintain the pdp ctx alive during all this time. Extra code is added to
gtp_delete_pdp_resp() since it's now possible to match it and push it up
to the user cb_conf.

This way, cb_conf() can be used for locally-initiated DEL CTX REQ, while
delete_context() cb is left for remotely-initiated DEL CTX REQ. In this
later case, when the DEL CTX RESP is sent the ctx is deleted and the
delete_context() is called, where the user can do related actions or
trigger consequence events (in the case of SGSN, it will drop all
related GGSN bits for that PDP ctx and forward the DEACT PDP CTX to the
MS).

Change-Id: I29d366253bb98dcba328c7ce8aa3e4daf8f75e6c
---
M gtp/gtp.c
M gtp/gtp.h
2 files changed, 74 insertions(+), 38 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Neels Hofmeyr: Looks good to me, but someone else must approve
  Jenkins Builder: Verified



diff --git a/gtp/gtp.c b/gtp/gtp.c
index 1309cb5..95abbef 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -2337,16 +2337,66 @@
 	return EOF;
 }
 
-/* API: Send Delete PDP Context Request */
+/* API: Deprecated. Send Delete PDP Context Request And free pdp ctx. */
 int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
 			   int teardown)
 {
+	struct pdp_t *linked_pdp;
+	struct pdp_t *secondary_pdp;
+	int n;
+
+	if (pdp_getgtp1(&linked_pdp, pdp->teic_own)) {
+		LOGP(DLGTP, LOGL_ERROR,
+			"Unknown linked PDP context: %u\n", pdp->teic_own);
+		return EOF;
+	}
+
+	if (gtp_delete_context_req2(gsn, pdp, cbp, teardown) == EOF)
+		return EOF;
+
+	if (teardown) {		/* Remove all contexts */
+		for (n = 0; n < PDP_MAXNSAPI; n++) {
+			if (linked_pdp->secondary_tei[n]) {
+				if (pdp_getgtp1
+				    (&secondary_pdp,
+				     linked_pdp->secondary_tei[n])) {
+					LOGP(DLGTP, LOGL_ERROR,
+						"Unknown secondary PDP context\n");
+					return EOF;
+				}
+				if (linked_pdp != secondary_pdp) {
+					if (gsn->cb_delete_context)
+						gsn->cb_delete_context
+						    (secondary_pdp);
+					pdp_freepdp(secondary_pdp);
+				}
+			}
+		}
+		if (gsn->cb_delete_context)
+			gsn->cb_delete_context(linked_pdp);
+		pdp_freepdp(linked_pdp);
+	} else {
+		if (gsn->cb_delete_context)
+			gsn->cb_delete_context(pdp);
+		if (pdp == linked_pdp) {
+			linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
+			linked_pdp->nodata = 1;
+		} else
+			pdp_freepdp(pdp);
+	}
+
+	return 0;
+}
+
+/* API: Send Delete PDP Context Request. PDP CTX shall be free'd by user at cb_conf(GTP_DELETE_PDP_RSP) */
+int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
+			   int teardown)
+{
 	union gtp_packet packet;
 	unsigned int length =
 	    get_default_gtp(pdp->version, GTP_DELETE_PDP_REQ, &packet);
 	struct in_addr addr;
 	struct pdp_t *linked_pdp;
-	struct pdp_t *secondary_pdp;
 	int n;
 	int count = 0;
 
@@ -2383,37 +2433,6 @@
 
 	gtp_req(gsn, pdp->version, pdp, &packet, length, &addr, cbp);
 
-	if (teardown) {		/* Remove all contexts */
-		for (n = 0; n < PDP_MAXNSAPI; n++) {
-			if (linked_pdp->secondary_tei[n]) {
-				if (pdp_getgtp1
-				    (&secondary_pdp,
-				     linked_pdp->secondary_tei[n])) {
-					LOGP(DLGTP, LOGL_ERROR,
-						"Unknown secondary PDP context\n");
-					return EOF;
-				}
-				if (linked_pdp != secondary_pdp) {
-					if (gsn->cb_delete_context)
-						gsn->cb_delete_context
-						    (secondary_pdp);
-					pdp_freepdp(secondary_pdp);
-				}
-			}
-		}
-		if (gsn->cb_delete_context)
-			gsn->cb_delete_context(linked_pdp);
-		pdp_freepdp(linked_pdp);
-	} else {
-		if (gsn->cb_delete_context)
-			gsn->cb_delete_context(pdp);
-		if (pdp == linked_pdp) {
-			linked_pdp->secondary_tei[pdp->nsapi & 0xf0] = 0;
-			linked_pdp->nodata = 1;
-		} else
-			pdp_freepdp(pdp);
-	}
-
 	return 0;
 }
 
@@ -2573,19 +2592,32 @@
 	uint8_t cause;
 	void *cbp = NULL;
 	uint8_t type = 0;
+	struct pdp_t *pdp = NULL;
 	int hlen = get_hlen(pack);
 
 	/* Remove packet from queue */
 	if (gtp_conf(gsn, version, peer, pack, len, &type, &cbp))
 		return EOF;
 
+	/* Find the context in question. It may not be available if gtp_delete_context_req
+	 * was used and as a result the PDP ctx was already freed */
+	if (pdp_getgtp1(&pdp, get_tei(pack))) {
+		gsn->err_unknownpdp++;
+		GTP_LOGPKG(LOGL_NOTICE, peer, pack, len,
+			    "Unknown PDP context: %u (expected if gtp_delete_context_req is used)\n",
+			     get_tei(pack));
+		if (gsn->cb_conf)
+			gsn->cb_conf(type, EOF, NULL, cbp);
+		return EOF;
+	}
+
 	/* Decode information elements */
 	if (gtpie_decaps(ie, version, pack + hlen, len - hlen)) {
 		gsn->invalid++;
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Invalid message format\n");
 		if (gsn->cb_conf)
-			gsn->cb_conf(type, EOF, NULL, cbp);
+			gsn->cb_conf(type, EOF, pdp, cbp);
 		return EOF;
 	}
 
@@ -2595,7 +2627,7 @@
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Missing mandatory information field\n");
 		if (gsn->cb_conf)
-			gsn->cb_conf(type, EOF, NULL, cbp);
+			gsn->cb_conf(type, EOF, pdp, cbp);
 		return EOF;
 	}
 
@@ -2605,13 +2637,13 @@
 		GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
 			    "Unexpected cause value received: %d\n", cause);
 		if (gsn->cb_conf)
-			gsn->cb_conf(type, cause, NULL, cbp);
+			gsn->cb_conf(type, cause, pdp, cbp);
 		return EOF;
 	}
 
 	/* Callback function to notify application */
 	if (gsn->cb_conf)
-		gsn->cb_conf(type, cause, NULL, cbp);
+		gsn->cb_conf(type, cause, pdp, cbp);
 
 	return 0;
 }
diff --git a/gtp/gtp.h b/gtp/gtp.h
index 8f8e293..f185424 100644
--- a/gtp/gtp.h
+++ b/gtp/gtp.h
@@ -13,6 +13,7 @@
 #define _GTP_H
 
 #include <osmocom/core/utils.h>
+#include <osmocom/core/defs.h>
 
 #define GTP_MODE_GGSN 1
 #define GTP_MODE_SGSN 2
@@ -323,7 +324,10 @@
 			      void *cbp, struct in_addr *inetaddr);
 
 extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
-				  void *cbp, int teardown);
+				  void *cbp, int teardown)
+		OSMO_DEPRECATED("Use gtp_delete_context_req2() instead, to avoid freeing pdp ctx before reply");
+extern int gtp_delete_context_req2(struct gsn_t *gsn, struct pdp_t *pdp,
+				   void *cbp, int teardown);
 
 extern int gtp_data_req(struct gsn_t *gsn, struct pdp_t *pdp,
 			void *pack, unsigned len);

-- 
To view, visit https://gerrit.osmocom.org/10006
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-ggsn
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: I29d366253bb98dcba328c7ce8aa3e4daf8f75e6c
Gerrit-Change-Number: 10006
Gerrit-PatchSet: 3
Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180721/5bf68509/attachment.htm>


More information about the gerrit-log mailing list