mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-ggsn.git
synced 2025-10-23 08:22:07 +00:00
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
This commit is contained in:
@@ -8,3 +8,5 @@
|
|||||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
||||||
#library what description / commit summary line
|
#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 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()
|
@@ -497,6 +497,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
|
|||||||
|
|
||||||
/* Initialise call back functions */
|
/* Initialise call back functions */
|
||||||
(*gsn)->cb_create_context_ind = 0;
|
(*gsn)->cb_create_context_ind = 0;
|
||||||
|
(*gsn)->cb_update_context_ind = 0;
|
||||||
(*gsn)->cb_delete_context = 0;
|
(*gsn)->cb_delete_context = 0;
|
||||||
(*gsn)->cb_unsup_ind = 0;
|
(*gsn)->cb_unsup_ind = 0;
|
||||||
(*gsn)->cb_conf = 0;
|
(*gsn)->cb_conf = 0;
|
||||||
@@ -563,6 +564,13 @@ int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
|
|||||||
return 0;
|
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)
|
int gtp_retrans(struct gsn_t *gsn)
|
||||||
{
|
{
|
||||||
/* dummy API, deprecated. */
|
/* dummy API, deprecated. */
|
||||||
|
84
gtp/gtp.c
84
gtp/gtp.c
@@ -1696,10 +1696,11 @@ int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp, void *cbp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Send Update PDP Context Response */
|
/* Send Update PDP Context Response */
|
||||||
static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
|
static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
|
||||||
struct sockaddr_in *peer, int fd,
|
struct sockaddr_in *peer, int fd,
|
||||||
void *pack, unsigned len,
|
uint16_t seq, uint64_t tid,
|
||||||
struct pdp_t *pdp, uint8_t cause)
|
struct pdp_t *pdp, uint8_t cause)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -1760,7 +1761,22 @@ static int gtp_update_pdp_resp(struct gsn_t *gsn, uint8_t version,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return gtp_resp(version, gsn, pdp, &packet, length, peer,
|
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 */
|
/* Handle Update PDP Context Request */
|
||||||
@@ -1768,13 +1784,15 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
struct sockaddr_in *peer, int fd,
|
struct sockaddr_in *peer, int fd,
|
||||||
void *pack, unsigned len)
|
void *pack, unsigned len)
|
||||||
{
|
{
|
||||||
struct pdp_t *pdp;
|
struct pdp_t *pdp = NULL;
|
||||||
struct pdp_t pdp_backup;
|
struct pdp_t pdp_backup;
|
||||||
union gtpie_member *ie[GTPIE_SIZE];
|
union gtpie_member *ie[GTPIE_SIZE];
|
||||||
uint8_t recovery;
|
uint8_t recovery;
|
||||||
|
int rc;
|
||||||
|
|
||||||
uint16_t seq = get_seq(pack);
|
uint16_t seq = get_seq(pack);
|
||||||
int hlen = get_hlen(pack);
|
int hlen = get_hlen(pack);
|
||||||
|
uint64_t tid = get_tid(pack);
|
||||||
|
|
||||||
uint64_t imsi;
|
uint64_t imsi;
|
||||||
uint8_t nsapi;
|
uint8_t nsapi;
|
||||||
@@ -1792,8 +1810,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
if (0 == version)
|
if (0 == version)
|
||||||
return EOF;
|
return EOF;
|
||||||
else
|
else
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, NULL,
|
tid, NULL,
|
||||||
GTPCAUSE_INVALID_MESSAGE);
|
GTPCAUSE_INVALID_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1808,8 +1826,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||||
"Unknown PDP context: TID=0x%" PRIx64 "\n",
|
"Unknown PDP context: TID=0x%" PRIx64 "\n",
|
||||||
get_tid(pack));
|
get_tid(pack));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, NULL,
|
tid, NULL,
|
||||||
GTPCAUSE_NON_EXIST);
|
GTPCAUSE_NON_EXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1821,8 +1839,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
|
rate_ctr_inc2(gsn->ctrg, GSN_CTR_PKT_MISSING);
|
||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, NULL,
|
tid, NULL,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1835,7 +1853,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
|
"Unknown PDP context: TEI=0x%" PRIx32 "\n",
|
||||||
get_tei(pack));
|
get_tei(pack));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer,
|
return gtp_update_pdp_resp(gsn, version, peer,
|
||||||
fd, pack, len, NULL,
|
fd, seq, tid, NULL,
|
||||||
GTPCAUSE_NON_EXIST);
|
GTPCAUSE_NON_EXIST);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1846,7 +1864,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
"Unknown PDP context: IMSI=0x%" PRIx64
|
"Unknown PDP context: IMSI=0x%" PRIx64
|
||||||
" NSAPI=%" PRIu8 "\n", imsi, nsapi);
|
" NSAPI=%" PRIu8 "\n", imsi, nsapi);
|
||||||
return gtp_update_pdp_resp(gsn, version, peer,
|
return gtp_update_pdp_resp(gsn, version, peer,
|
||||||
fd, pack, len, NULL,
|
fd, seq, tid, NULL,
|
||||||
GTPCAUSE_NON_EXIST);
|
GTPCAUSE_NON_EXIST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1855,6 +1873,12 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
return EOF;
|
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 */
|
/* Make a backup copy in case anything is wrong */
|
||||||
memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
|
memcpy(&pdp_backup, pdp, sizeof(pdp_backup));
|
||||||
|
|
||||||
@@ -1865,8 +1889,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1882,8 +1906,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1892,8 +1916,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1906,8 +1930,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1923,8 +1947,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1951,7 +1975,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||||
"Missing mandatory information field\n");
|
"Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
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);
|
pdp, GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1963,7 +1987,7 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack, len,
|
||||||
"Missing mandatory information field\n");
|
"Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
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);
|
pdp, GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1976,8 +2000,8 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
GTP_LOGPKG(LOGL_ERROR, peer, pack,
|
||||||
len, "Missing mandatory information field\n");
|
len, "Missing mandatory information field\n");
|
||||||
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
memcpy(pdp, &pdp_backup, sizeof(pdp_backup));
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack,
|
return gtp_update_pdp_resp(gsn, version, peer, fd, seq,
|
||||||
len, pdp,
|
tid, pdp,
|
||||||
GTPCAUSE_MAN_IE_MISSING);
|
GTPCAUSE_MAN_IE_MISSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1994,11 +2018,19 @@ static int gtp_update_pdp_ind(struct gsn_t *gsn, uint8_t version,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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" */
|
/* Confirm to peer that things were "successful" */
|
||||||
return gtp_update_pdp_resp(gsn, version, peer, fd, pack, len, pdp,
|
rc = gtp_update_pdp_resp(gsn, version, peer, fd, seq, tid, pdp,
|
||||||
GTPCAUSE_ACC_REQ);
|
GTPCAUSE_ACC_REQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Confirm to peer that things were "successful" */
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle Update PDP Context Response */
|
/* Handle Update PDP Context Response */
|
||||||
static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
static int gtp_update_pdp_conf(struct gsn_t *gsn, uint8_t version,
|
||||||
struct sockaddr_in *peer, void *pack, unsigned len)
|
struct sockaddr_in *peer, void *pack, unsigned len)
|
||||||
|
@@ -99,6 +99,7 @@ struct gsn_t {
|
|||||||
/* Call back functions */
|
/* Call back functions */
|
||||||
int (*cb_delete_context) (struct pdp_t *);
|
int (*cb_delete_context) (struct pdp_t *);
|
||||||
int (*cb_create_context_ind) (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_unsup_ind) (struct sockaddr_in * peer);
|
||||||
int (*cb_extheader_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);
|
int (*cb_ran_info_relay_ind) (struct sockaddr_in *peer, union gtpie_member **ie);
|
||||||
@@ -134,6 +135,8 @@ extern int gtp_set_cb_create_context_ind(struct gsn_t *gsn,
|
|||||||
int (*cb_create_context_ind) (struct
|
int (*cb_create_context_ind) (struct
|
||||||
pdp_t *
|
pdp_t *
|
||||||
pdp));
|
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,
|
extern int gtp_set_cb_data_ind(struct gsn_t *gsn,
|
||||||
int (*cb_data_ind) (struct pdp_t * pdp,
|
int (*cb_data_ind) (struct pdp_t * pdp,
|
||||||
void *pack, unsigned len));
|
void *pack, unsigned len));
|
||||||
|
@@ -248,6 +248,9 @@ extern int gtp_create_context_resp(struct gsn_t *gsn, struct pdp_t *pdp,
|
|||||||
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
|
extern int gtp_update_context(struct gsn_t *gsn, struct pdp_t *pdp,
|
||||||
void *cbp, struct in_addr *inetaddr);
|
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,
|
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");
|
OSMO_DEPRECATED("Use gtp_delete_context_req2() instead, to avoid freeing pdp ctx before reply");
|
||||||
|
Reference in New Issue
Block a user