mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-upf.git
synced 2025-10-23 08:12:03 +00:00
Introduce hashtable to lookup session by F-TEID
This is a hot path when creating new sessions. Previous code would take ages specially when UPF already had thousands of sessions created and a new TEID to allocate was being looked up. Related: SYS#6398 Change-Id: I90ecbb07b242c1de2298261019f24aa5f5810fda
This commit is contained in:
@@ -69,7 +69,6 @@ struct up_session {
|
||||
struct up_session *up_session_find_or_add(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid);
|
||||
struct up_session *up_session_find_by_up_seid(struct up_peer *peer, uint64_t up_seid);
|
||||
struct up_session *up_session_find_by_cp_f_seid(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid);
|
||||
struct up_session *up_session_find_by_local_teid(struct up_peer *peer, uint32_t teid);
|
||||
|
||||
void up_session_set_msg_ctx(struct up_session *session, struct osmo_pfcp_msg *m);
|
||||
|
||||
@@ -83,7 +82,8 @@ int up_session_to_str_buf(char *buf, size_t buflen, struct up_session *session);
|
||||
char *up_session_to_str_c(void *ctx, struct up_session *session);
|
||||
|
||||
struct pdr {
|
||||
struct llist_head entry;
|
||||
struct llist_head entry; /* item in session->pdrs */
|
||||
struct hlist_node node_by_local_f_teid; /* item in g_upf->gtp.pdrs_by_local_f_teid */
|
||||
struct up_session *session;
|
||||
|
||||
struct osmo_pfcp_ie_create_pdr desc;
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include <osmocom/core/socket.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/core/hashtable.h>
|
||||
|
||||
struct osmo_tdef;
|
||||
struct ctrl_handle;
|
||||
@@ -118,6 +119,8 @@ struct g_upf {
|
||||
|
||||
struct {
|
||||
uint32_t next_local_teid_state;
|
||||
/* hashtable of (struct pdr)->node_by_local_f_teid: */
|
||||
DECLARE_HASHTABLE(pdrs_by_local_f_teid, 10);
|
||||
uint16_t next_echo_seq_nr;
|
||||
} gtp;
|
||||
|
||||
|
@@ -379,6 +379,8 @@ static struct pdr *pdr_find(struct up_session *session, uint16_t pdr_id)
|
||||
|
||||
static void pdr_del(struct pdr *pdr)
|
||||
{
|
||||
if (!hlist_unhashed(&pdr->node_by_local_f_teid))
|
||||
hash_del(&pdr->node_by_local_f_teid);
|
||||
llist_del(&pdr->entry);
|
||||
talloc_free(pdr);
|
||||
}
|
||||
@@ -411,6 +413,7 @@ static struct pdr *pdr_create(struct up_session *session,
|
||||
.session = session,
|
||||
.desc = *create_pdr,
|
||||
};
|
||||
INIT_HLIST_NODE(&pdr->node_by_local_f_teid);
|
||||
llist_add_tail(&pdr->entry, &session->pdrs);
|
||||
|
||||
if (pdr->desc.far_id_present) {
|
||||
@@ -482,6 +485,7 @@ static struct pdr *pdr_create(struct up_session *session,
|
||||
.local_f_teid_present = true,
|
||||
.local_f_teid = *pdr->local_f_teid,
|
||||
};
|
||||
hash_add(g_upf->gtp.pdrs_by_local_f_teid, &pdr->node_by_local_f_teid, pdr->local_f_teid->fixed.teid);
|
||||
} else {
|
||||
created_pdr[*created_pdr_count] = (struct osmo_pfcp_ie_created_pdr){
|
||||
.pdr_id = pdr->desc.pdr_id,
|
||||
@@ -1054,22 +1058,6 @@ struct up_session *up_session_find_by_cp_f_seid(struct up_peer *peer, const stru
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct up_session *up_session_find_by_local_teid(struct up_peer *peer, uint32_t teid)
|
||||
{
|
||||
struct up_session *session;
|
||||
int bkt;
|
||||
hash_for_each(peer->sessions_by_up_seid, bkt, session, node_by_up_seid) {
|
||||
struct pdr *pdr;
|
||||
llist_for_each_entry(pdr, &session->pdrs, entry) {
|
||||
if (!pdr->local_f_teid)
|
||||
continue;
|
||||
if (pdr->local_f_teid->fixed.teid == teid)
|
||||
return session;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool action_is_forw(const struct osmo_pfcp_ie_apply_action *aa)
|
||||
{
|
||||
return osmo_pfcp_bits_get(aa->bits, OSMO_PFCP_APPLY_ACTION_FORW)
|
||||
|
@@ -78,6 +78,7 @@ void g_upf_alloc(void *ctx)
|
||||
INIT_LLIST_HEAD(&g_upf->tunend.vty_cfg.devs);
|
||||
INIT_LLIST_HEAD(&g_upf->tunend.devs);
|
||||
INIT_LLIST_HEAD(&g_upf->netinst);
|
||||
hash_init(g_upf->gtp.pdrs_by_local_f_teid);
|
||||
}
|
||||
|
||||
int upf_pfcp_init(void)
|
||||
@@ -135,11 +136,13 @@ int upf_gtp_devs_open()
|
||||
|
||||
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;
|
||||
struct pdr *pdr;
|
||||
hash_for_each_possible(g_upf->gtp.pdrs_by_local_f_teid, pdr, node_by_local_f_teid, teid) {
|
||||
if (!pdr->local_f_teid)
|
||||
continue;
|
||||
if (pdr->local_f_teid->fixed.teid != teid)
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user