pespin submitted this change.
gtp: Allow setting callback to receive update_context_ind
This will be used by:
* SGSN: Get to know that RNC has gonne down according to GGSN (re-attempt
Direct Tunnel or go back to tun SGSN<->GGSN).
* GGSN: Maybe find out that Direct Flags are used (should be handled
internally directly in the rx path probably)
Related: OS#6512
Change-Id: Ic80a9a928c55b6ff85be96014920bb42793cb943
---
M TODO-RELEASE
M gtp/gsn.c
M gtp/gtp.c
M include/osmocom/gtp/gsn.h
M include/osmocom/gtp/gtp.h
5 files changed, 91 insertions(+), 27 deletions(-)
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 1815fce..905c234 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -8,3 +8,5 @@
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
libgtp append new field dir_tun_flags in struct pdp_t (older users not using the field should be fine since struct pdp_t is allocated internally)
+libgtp ABI break new field cb_create_context_ind in struct gsn_t
+libgtp new API gtp_set_cb_update_context_ind(), gtp_update_context_resp()
\ No newline at end of file
diff --git a/gtp/gsn.c b/gtp/gsn.c
index c23fb2a..612baf2 100644
--- a/gtp/gsn.c
+++ b/gtp/gsn.c
@@ -497,6 +497,7 @@
/* Initialise call back functions */
(*gsn)->cb_create_context_ind = 0;
+ (*gsn)->cb_update_context_ind = 0;
(*gsn)->cb_delete_context = 0;
(*gsn)->cb_unsup_ind = 0;
(*gsn)->cb_conf = 0;
@@ -563,6 +564,13 @@
return 0;
}
+int gtp_set_cb_update_context_ind(struct gsn_t *gsn,
+ int (*cb_update_context_ind)(struct pdp_t *pdp))
+{
+ gsn->cb_update_context_ind = cb_update_context_ind;
+ return 0;
+}
+
int gtp_retrans(struct gsn_t *gsn)
{
/* dummy API, deprecated. */
diff --git a/gtp/gtp.c b/gtp/gtp.c
index 9b68315..02cf8a3 100644
--- a/gtp/gtp.c
+++ b/gtp/gtp.c
@@ -1696,10 +1696,11 @@
return 0;
}
+
/* Send Update PDP Context Response */
static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
struct sockaddr_in *peer, int fd,
- void *pack, unsigned len,
+ uint16_t seq, uint64_t tid,
struct pdp_t *pdp, uint8_t cause)
{
@@ -1760,7 +1761,22 @@
}
return gtp_resp(version, gsn, pdp, &packet, length, peer,
- fd, get_seq(pack), get_tid(pack));
+ fd, seq, tid);
+}
+
+
+/* API: Application response to context indication */
+int gtp_update_context_resp(struct gsn_t *gsn, struct pdp_t *pdp, int cause)
+{
+
+ /* Now send off a reply to the peer */
+ gtp_update_pdp_resp(gsn, pdp->version, &pdp->sa_peer,
+ pdp->fd, pdp->seq, pdp->tid, pdp, cause);
+
+ if (!gtp_cause_successful(cause))
+ gtp_freepdp(gsn, pdp);
+
+ return 0;
}
/* Handle Update PDP Context Request */
@@ -1768,13 +1784,15 @@
struct sockaddr_in *peer, int fd,
void *pack, unsigned len)
{
- struct pdp_t *pdp;
+ struct pdp_t *pdp = NULL;
struct pdp_t pdp_backup;
union gtpie_member *ie[GTPIE_SIZE];
uint8_t recovery;
+ int rc;
uint16_t seq = get_seq(pack);
int hlen = get_hlen(pack);
+ uint64_t tid = get_tid(pack);
uint64_t imsi;
uint8_t nsapi;
@@ -1792,8 +1810,8 @@
if (0 == version)
return EOF;
else
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_INVALID_MESSAGE);
}
@@ -1808,8 +1826,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Unknown PDP context: TID=0x%" PRIx64 "\n",
get_tid(pack));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_NON_EXIST);
}
@@ -1821,8 +1839,8 @@
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, NULL,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, NULL,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1835,7 +1853,7 @@
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
get_tei(pack));
return gtp_update_pdp_resp(gsn, version, peer,
- fd, pack, len, NULL,
+ fd, seq, tid, NULL,
GTPCAUSE_NON_EXIST);
}
} else {
@@ -1846,7 +1864,7 @@
"Unknown PDP context: IMSI=0x%" PRIx64
" NSAPI=%" PRIu8 "\n", imsi, nsapi);
return gtp_update_pdp_resp(gsn, version, peer,
- fd, pack, len, NULL,
+ fd, seq, tid, NULL,
GTPCAUSE_NON_EXIST);
}
}
@@ -1855,6 +1873,12 @@
return EOF;
}
+ /* Update internal state to be used when user calls gtp_update_context_resp(): */
+ pdp->seq = seq;
+ pdp->sa_peer = *peer;
+ pdp->fd = fd;
+ pdp->version = version;
+
/* Make a backup copy in case anything is wrong */
memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
@@ -1865,8 +1889,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
@@ -1882,8 +1906,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1892,8 +1916,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
@@ -1906,8 +1930,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1923,8 +1947,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
}
@@ -1951,7 +1975,7 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid,
pdp, GTPCAUSE_MAN_IE_MISSING);
}
@@ -1963,7 +1987,7 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
"Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid,
pdp, GTPCAUSE_MAN_IE_MISSING);
}
@@ -1976,8 +2000,8 @@
GTP_LOGPKG(LOGL_ERROR, peer, pack,
len, "Missing mandatory information field\n");
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
- len, pdp,
+ return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
+ tid, pdp,
GTPCAUSE_MAN_IE_MISSING);
}
@@ -1994,9 +2018,17 @@
}
}
+ /* Callback function to validate login */
+ if (gsn->cb_update_context_ind != 0)
+ rc = gsn->cb_update_context_ind(pdp);
+ else {
+ /* Confirm to peer that things were "successful" */
+ rc = gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid, pdp,
+ GTPCAUSE_ACC_REQ);
+ }
+
/* Confirm to peer that things were "successful" */
- return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
- GTPCAUSE_ACC_REQ);
+ return rc;
}
/* Handle Update PDP Context Response */
diff --git a/include/osmocom/gtp/gsn.h b/include/osmocom/gtp/gsn.h
index 936db9b..006fdfd 100644
--- a/include/osmocom/gtp/gsn.h
+++ b/include/osmocom/gtp/gsn.h
@@ -99,6 +99,7 @@
/* Call back functions */
int (*cb_delete_context) (struct pdp_t *);
int (*cb_create_context_ind) (struct pdp_t *);
+ int (*cb_update_context_ind)(struct pdp_t *pdp);
int (*cb_unsup_ind) (struct sockaddr_in * peer);
int (*cb_extheader_ind) (struct sockaddr_in * peer);
int (*cb_ran_info_relay_ind) (struct sockaddr_in *peer, union gtpie_member **ie);
@@ -134,6 +135,8 @@
int (*cb_create_context_ind) (struct
pdp_t *
pdp));
+extern int gtp_set_cb_update_context_ind(struct gsn_t *gsn,
+ int (*cb_update_context_ind)(struct pdp_t *pdp));
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
int (*cb_data_ind) (struct pdp_t * pdp,
void *pack, unsigned len));
diff --git a/include/osmocom/gtp/gtp.h b/include/osmocom/gtp/gtp.h
index e3c66c9..001a696 100644
--- a/include/osmocom/gtp/gtp.h
+++ b/include/osmocom/gtp/gtp.h
@@ -248,6 +248,9 @@
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, struct in_addr *inetaddr);
+extern int gtp_update_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
+ int cause);
+
extern int gtp_delete_context_req(struct gsn_t *gsn, struct pdp_t *pdp,
void *cbp, int teardown)
OSMO_DEPRECATED("Use gtp_delete_context_req2() instead, to avoid freeing pdp ctx before reply");
To view, visit change 37597. To unsubscribe, or for help writing mail filters, visit settings.