gtp: Introduce new pdp APIs (and deprecate old ones) to support multiple GSN

Move static global pdp storage arrays to be per GSN. This way now
several GSN per process are supported without collisions.

* pdp_init() is defined in public API but it's actually only intended
for use (and currently only used) internally in gtp_new(). So let's
document that and re-use it for backward compatibility with now
deprecated API, where only one GSN per process is supported.

* Back pointer to gsn_t (pdp->gsn) moved from gtp.c:gtp_new() to
gtp_pdp_newpdp(), since it makes more sense to have it there. This way
backpointer is always set, even in case were app calls pdp_newpdp() API
directly instead of creating them through gtp.c, like osmo-sgsn does.

* Create new versions of required APIs with a pointer to gsn_t where the
pdp ctx is to be created/found. Some APIs receiving a pointer to a pdp
ctx can be left intact because we have a backpointer to its gsn_t.

* pdp_getpdp() is nowhere used, and makes little sense now that we have
pdpa reachable in gsn->pdpa, so let's deprecate it without adding a
replacement.

* Deprecate gtp.h gtp_newpdp(), since it's nowhere used and useless
(does same as new gtp_pdp_newpdp() and doesn't allow for old_pdp to be
passed as parameter).

Fixes: OS#2873
Change-Id: I653cbdc185165592d985e3efab6e3f1add97877b
This commit is contained in:
Pau Espin 2019-05-31 15:42:49 +02:00
parent 5560001af5
commit eefa30dce8
5 changed files with 90 additions and 37 deletions

View File

@ -7,3 +7,6 @@
# If any interfaces have been added since the last public release: c:r:a + 1.
# If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line
libgtp Several new APIs added see I653cbdc185165592d985e3efab6e3f1add97877b
libgtp API (non-used externally) pdp_init modified see I653cbdc185165592d985e3efab6e3f1add97877b
libgtp Several pdp_* APIs marked as deprecated see I653cbdc185165592d985e3efab6e3f1add97877b

View File

@ -131,16 +131,12 @@ const struct value_string gtp_type_names[] = {
{ 0, NULL }
};
/* gtp_new */
/* gtp_free */
/* Deprecated, use gtp_pdp_newpdp() instead */
int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
uint64_t imsi, uint8_t nsapi)
{
int rc;
rc = pdp_newpdp(pdp, imsi, nsapi, NULL);
if (!rc && *pdp)
(*pdp)->gsn = gsn;
rc = gtp_pdp_newpdp(gsn, pdp, imsi, nsapi, NULL);
return rc;
}
@ -849,7 +845,7 @@ int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
queue_new(&(*gsn)->queue_resp);
/* Initialise pdp table */
pdp_init();
pdp_init(*gsn);
/* Initialise call back functions */
(*gsn)->cb_create_context_ind = 0;
@ -1681,9 +1677,7 @@ int gtp_create_pdp_ind(struct gsn_t *gsn, int version,
}
}
pdp_newpdp(&pdp, pdp->imsi, pdp->nsapi, pdp);
if (pdp)
pdp->gsn = gsn;
gtp_pdp_newpdp(gsn, &pdp, pdp->imsi, pdp->nsapi, pdp);
/* Callback function to validate login */
if (gsn->cb_create_context_ind != 0)

View File

@ -15,6 +15,8 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/defs.h>
#include "pdp.h"
#define GTP_MODE_GGSN 1
#define GTP_MODE_SGSN 2
@ -263,6 +265,9 @@ struct gsn_t {
struct queue_t *queue_req; /* Request queue */
struct queue_t *queue_resp; /* Response queue */
struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
/* Call back functions */
int (*cb_delete_context) (struct pdp_t *);
int (*cb_create_context_ind) (struct pdp_t *);
@ -307,7 +312,7 @@ extern int gtp_new(struct gsn_t **gsn, char *statedir, struct in_addr *listen,
extern int gtp_free(struct gsn_t *gsn);
extern int gtp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp,
uint64_t imsi, uint8_t nsapi);
uint64_t imsi, uint8_t nsapi) OSMO_DEPRECATED("Use gtp_pdp_newpdp() instead");
extern int gtp_freepdp(struct gsn_t *gsn, struct pdp_t *pdp);
extern int gtp_freepdp_teardown(struct gsn_t *gsn, struct pdp_t *pdp);

View File

@ -32,13 +32,6 @@
#include "gtp.h"
#include "lookupa.h"
/* ***********************************************************
* Global variables TODO: most should be moved to gsn_t
*************************************************************/
static struct pdp_t pdpa[PDP_MAX]; /* PDP storage */
static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
/* ***********************************************************
* Functions related to PDP storage
*
@ -111,11 +104,16 @@ static struct pdp_t *hashtid[PDP_MAX]; /* Hash table for IMSI + NSAPI */
*
*************************************************************/
int pdp_init()
static struct gsn_t *g_gsn;
int pdp_init(struct gsn_t *gsn)
{
memset(&pdpa, 0, sizeof(pdpa));
memset(&hashtid, 0, sizeof(hashtid));
/* memset(&haship, 0, sizeof(haship)); */
if(!g_gsn) {
g_gsn = gsn;
} else {
LOGP(DLGTP, LOGL_FATAL, "This interface is depreacted and doesn't support multiple GGSN!");
return -1;
}
return 0;
}
@ -123,6 +121,13 @@ int pdp_init()
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old)
{
return gtp_pdp_newpdp(g_gsn, pdp, imsi, nsapi, pdp_old);
}
int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old)
{
struct pdp_t *pdpa = gsn->pdpa;
int n;
for (n = 0; n < PDP_MAX; n++) { /* TODO: Need to do better than linear search */
if (pdpa[n].inuse == 0) {
@ -132,6 +137,7 @@ int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
else
memset(*pdp, 0, sizeof(struct pdp_t));
(*pdp)->inuse = 1;
(*pdp)->gsn = gsn;
(*pdp)->imsi = imsi;
(*pdp)->nsapi = nsapi;
(*pdp)->fllc = (uint16_t) n + 1;
@ -159,6 +165,8 @@ int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
int pdp_freepdp(struct pdp_t *pdp)
{
struct pdp_t *pdpa = pdp->gsn->pdpa;
pdp_tiddel(pdp);
/* Remove any references in primary context */
@ -173,12 +181,20 @@ int pdp_freepdp(struct pdp_t *pdp)
int pdp_getpdp(struct pdp_t **pdp)
{
*pdp = &pdpa[0];
*pdp = &g_gsn->pdpa[0];
return 0;
}
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
{
return gtp_pdp_getgtp0(g_gsn, pdp, fl);
}
int gtp_pdp_getgtp0(struct gsn_t *gsn, struct pdp_t **pdp, uint16_t fl)
{
struct pdp_t *pdpa = gsn->pdpa;
if ((fl > PDP_MAX) || (fl < 1)) {
return EOF; /* Not found */
} else {
@ -193,6 +209,13 @@ int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl)
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
{
return gtp_pdp_getgtp1(g_gsn, pdp, tei);
}
int gtp_pdp_getgtp1(struct gsn_t *gsn, struct pdp_t **pdp, uint32_t tei)
{
struct pdp_t *pdpa = gsn->pdpa;
if ((tei > PDP_MAX) || (tei < 1)) {
return EOF; /* Not found */
} else {
@ -208,6 +231,12 @@ int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei)
/* get a PDP based on the *peer* address + TEI-Data. Used for matching inbound Error Ind */
int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn)
{
return gtp_pdp_getgtp1_peer_d(g_gsn, pdp, peer, teid_gn);
}
int gtp_pdp_getgtp1_peer_d(struct gsn_t *gsn, struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn)
{
struct pdp_t *pdpa = gsn->pdpa;
unsigned int i;
/* this is O(n) but we don't have (nor want) another hash... */
@ -230,6 +259,7 @@ int pdp_tidhash(uint64_t tid)
int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
{
struct pdp_t **hashtid = pdp->gsn->hashtid;
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
@ -248,6 +278,7 @@ int pdp_tidset(struct pdp_t *pdp, uint64_t tid)
int pdp_tiddel(struct pdp_t *pdp)
{
struct pdp_t **hashtid = pdp->gsn->hashtid;
int hash = pdp_tidhash(pdp->tid);
struct pdp_t *pdp2;
struct pdp_t *pdp_prev = NULL;
@ -269,6 +300,12 @@ int pdp_tiddel(struct pdp_t *pdp)
int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
{
return gtp_pdp_tidget(g_gsn, pdp, tid);
}
int gtp_pdp_tidget(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t tid)
{
struct pdp_t **hashtid = gsn->hashtid;
int hash = pdp_tidhash(tid);
struct pdp_t *pdp2;
DEBUGP(DLGTP, "Begin pdp_tidget tid = %"PRIx64"\n", tid);
@ -285,7 +322,12 @@ int pdp_tidget(struct pdp_t **pdp, uint64_t tid)
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return pdp_tidget(pdp,
return gtp_pdp_getimsi(g_gsn, pdp, imsi, nsapi);
}
int gtp_pdp_getimsi(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi)
{
return gtp_pdp_tidget(gsn, pdp,
(imsi & 0x0fffffffffffffffull) +
((uint64_t) nsapi << 60));
}

View File

@ -15,6 +15,8 @@
#include <stdbool.h>
#include <osmocom/core/defs.h>
struct gsn_t;
#define LOGPDPX(ss, level, pdp, fmt, args...) \
@ -235,33 +237,40 @@ struct pdp_t {
/* to be used by libgtp callers/users (to attach their own private state) */
void *priv;
struct gsn_t *gsn;
struct gsn_t *gsn; /* Back pointer to GSN where this pdp ctx belongs to */
bool tx_gpdu_seq; /* Transmit (true) or suppress G-PDU sequence numbers */
};
/* functions related to pdp_t management */
int pdp_init();
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old);
int gtp_pdp_newpdp(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi,
uint8_t nsapi, struct pdp_t *pdp_old);
int pdp_freepdp(struct pdp_t *pdp);
int pdp_getpdp(struct pdp_t **pdp);
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl);
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei);
int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn);
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi);
int gtp_pdp_getgtp0(struct gsn_t *gsn, struct pdp_t **pdp, uint16_t fl);
int gtp_pdp_getgtp1(struct gsn_t *gsn, struct pdp_t **pdp, uint32_t tei);
int gtp_pdp_getgtp1_peer_d(struct gsn_t *gsn, struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn);
int gtp_pdp_getimsi(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi);
int gtp_pdp_tidget(struct gsn_t *gsn, struct pdp_t **pdp, uint64_t tid);
int pdp_tidhash(uint64_t tid);
int pdp_tidset(struct pdp_t *pdp, uint64_t tid);
int pdp_tiddel(struct pdp_t *pdp);
int pdp_tidget(struct pdp_t **pdp, uint64_t tid);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
void pdp_set_imsi_nsapi(struct pdp_t *pdp, uint64_t teid);
unsigned int pdp_count_secondary(struct pdp_t *pdp);
uint64_t pdp_gettid(uint64_t imsi, uint8_t nsapi);
/* Deprecated APIs (support for only 1 GSN per process). Must be used only after first call to gtp_new() and until it is freed. */
int pdp_init(struct gsn_t *gsn); /* Use only allowed inside libgtp to keep compatiblity with deprecated APIs defined here. */
int pdp_newpdp(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi,
struct pdp_t *pdp_old) OSMO_DEPRECATED("Use gtp_pdp_newpdp() instead");
int pdp_getpdp(struct pdp_t **pdp) OSMO_DEPRECATED("Use gsn_t->pdpa field instead");
int pdp_getgtp0(struct pdp_t **pdp, uint16_t fl) OSMO_DEPRECATED("Use gtp_pdp_getgtp0() instead");
int pdp_getgtp1(struct pdp_t **pdp, uint32_t tei) OSMO_DEPRECATED("Use gtp_pdp_getgtp1() instead");
int pdp_getgtp1_peer_d(struct pdp_t **pdp, const struct sockaddr_in *peer, uint32_t teid_gn) OSMO_DEPRECATED("Use gtp_pdp_getgtp1_peer_d() instead");
int pdp_getimsi(struct pdp_t **pdp, uint64_t imsi, uint8_t nsapi) OSMO_DEPRECATED("Use gtp_pdp_getimsi() instead");
int pdp_tidget(struct pdp_t **pdp, uint64_t tid) OSMO_DEPRECATED("Use gtp_pdp_tidget() instead");
#endif /* !_PDP_H */