move next_teid from up_endpoint to g_upf

up_endpoint is about the PFCP endpoint, handing out local TEID is about
local GTP endpoints. Move the TEID allocation to g_upf / upf.c.

An upcoming patch will use a hash table in g_upf to speed up lookup
whether a local TEID is already in use; cosmetically prepare for that.

Change-Id: I8eae5b53c563400ddfded264678d9cfb28b6f737
This commit is contained in:
Neels Janosch Hofmeyr
2023-02-10 23:00:19 +01:00
parent 1961cf90b5
commit 8e17c9933c
5 changed files with 40 additions and 35 deletions

View File

@@ -39,11 +39,9 @@ struct up_endpoint {
struct llist_head peers;
uint64_t next_seid_state;
uint32_t next_teid_state;
};
struct up_endpoint *up_endpoint_init(void *ctx, const struct osmo_sockaddr *local_addr);
void up_endpoint_free(struct up_endpoint **ep);
uint64_t up_endpoint_next_seid(struct up_endpoint *ep);
uint32_t up_endpoint_next_teid(struct up_endpoint *ep);

View File

@@ -115,6 +115,10 @@ struct g_upf {
uint32_t next_chain_id_state;
} tunmap;
struct {
uint32_t next_local_teid_state;
} gtp;
struct llist_head netinst;
};
@@ -134,3 +138,5 @@ int upf_pfcp_listen();
int upf_gtp_devs_open();
void upf_gtp_devs_close();
uint32_t upf_next_local_teid(void);

View File

@@ -271,17 +271,6 @@ static struct up_session *up_endpoint_find_session(struct up_endpoint *ep, uint6
return NULL;
}
static struct up_session *up_endpoint_find_session_by_local_teid(struct up_endpoint *ep, uint32_t teid)
{
struct up_peer *peer;
llist_for_each_entry(peer, &ep->peers, entry) {
struct up_session *session = up_session_find_by_local_teid(peer, teid);
if (session)
return session;
}
return NULL;
}
uint64_t up_endpoint_next_seid(struct up_endpoint *ep)
{
uint64_t sanity;
@@ -294,26 +283,6 @@ uint64_t up_endpoint_next_seid(struct up_endpoint *ep)
return 0;
}
static uint32_t up_endpoint_inc_teid(struct up_endpoint *ep)
{
ep->next_teid_state++;
if (!ep->next_teid_state)
ep->next_teid_state++;
return ep->next_teid_state;
}
uint32_t up_endpoint_next_teid(struct up_endpoint *ep)
{
uint32_t sanity;
for (sanity = 2342; sanity; sanity--) {
uint32_t next_teid = up_endpoint_inc_teid(ep);
if (up_endpoint_find_session_by_local_teid(ep, next_teid))
continue;
return next_teid;
}
return 0;
}
void up_endpoint_free(struct up_endpoint **_ep)
{
struct up_peer *peer;

View File

@@ -185,7 +185,6 @@ static enum osmo_pfcp_cause up_session_choose_f_teid(struct up_session *session,
bool choose_id_present, uint8_t choose_id,
const char *netinst_name)
{
struct up_endpoint *up_ep = session->up_peer->up_endpoint;
struct chosen_f_teid *chosen = NULL;
if (choose_id_present)
@@ -206,7 +205,7 @@ static enum osmo_pfcp_cause up_session_choose_f_teid(struct up_session *session,
return rc;
/* Choose a new TEID */
dst->fixed.teid = up_endpoint_next_teid(up_ep);
dst->fixed.teid = upf_next_local_teid();
if (dst->fixed.teid == 0) {
LOGPFSML(session->fi, LOGL_ERROR, "Failed to allocate an unused TEID\n");
return OSMO_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION;

View File

@@ -29,6 +29,8 @@
#include <osmocom/upf/upf.h>
#include <osmocom/upf/up_endpoint.h>
#include <osmocom/upf/up_peer.h>
#include <osmocom/upf/up_session.h>
#include <osmocom/upf/upf_gtp.h>
struct g_upf *g_upf = NULL;
@@ -98,3 +100,34 @@ int upf_gtp_devs_open()
}
return 0;
}
static bool upf_is_local_teid_in_use(uint32_t teid)
{
struct up_peer *peer;
llist_for_each_entry(peer, &g_upf->pfcp.ep->peers, entry) {
struct up_session *session = up_session_find_by_local_teid(peer, teid);
if (session)
return true;
}
return false;
}
static uint32_t upf_next_local_teid_inc(void)
{
g_upf->gtp.next_local_teid_state++;
if (!g_upf->gtp.next_local_teid_state)
g_upf->gtp.next_local_teid_state++;
return g_upf->gtp.next_local_teid_state;
}
uint32_t upf_next_local_teid(void)
{
uint32_t sanity;
for (sanity = 2342; sanity; sanity--) {
uint32_t next_teid = upf_next_local_teid_inc();
if (upf_is_local_teid_in_use(next_teid))
continue;
return next_teid;
}
return 0;
}