From b6d689d677144613a83b382d3e09b423c159f220 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 17 Feb 2025 19:12:44 +0100 Subject: [PATCH] Introduce hashtable to look up gtp_tundev by local TEID Use this hashtable while looking up for tunend based on . This kind of look up is used every time a session is added or removed, which means potentially thousands of tunend sessions were being iterated linerarly every time. For simplification (easier/quicker hashtable key generation), reduce the whole key presented above to a more general one based on "access.local.teid". This is usually enough since we are anyways allocating local TEIDs globally per tunnel without caring about remote address. Change-Id: Ib12ecc8ce87175071c52c0ed2217a29d901f0f05 --- include/osmocom/upf/upf_gtp.h | 3 +++ src/osmo-upf/upf_gtp.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/osmocom/upf/upf_gtp.h b/include/osmocom/upf/upf_gtp.h index b4cd3df..1162861 100644 --- a/include/osmocom/upf/upf_gtp.h +++ b/include/osmocom/upf/upf_gtp.h @@ -24,6 +24,7 @@ #pragma once #include +#include #include #include @@ -55,6 +56,8 @@ struct upf_gtp_dev { /* list of struct upf_gtp_tunend */ struct llist_head tunnels; + /* hashtable of (struct upf_gtp_tunen) with key desc.access.local.teid */ + DECLARE_HASHTABLE(tunnels_by_local_f_teid, 10); }; /* Description of a GTP encapsulation / decapsulation. diff --git a/src/osmo-upf/upf_gtp.c b/src/osmo-upf/upf_gtp.c index 528937b..4cbebcd 100644 --- a/src/osmo-upf/upf_gtp.c +++ b/src/osmo-upf/upf_gtp.c @@ -134,6 +134,7 @@ static struct upf_gtp_dev *upf_gtp_dev_alloc(const char *name, const char *local .gtpv1.ofd.fd = -1, }; INIT_LLIST_HEAD(&dev->tunnels); + hash_init(dev->tunnels_by_local_f_teid); osmo_sockaddr_str_from_str(&addr_conv, local_addr, PORT_GTP0_U); @@ -318,7 +319,8 @@ int upf_gtp_genl_ensure_open() } struct upf_gtp_tunend { - struct llist_head entry; + struct llist_head entry; /* item in (struct upf_gtp_dev)->tunnels */ + struct hlist_node node_by_local_f_teid; /* item in g_upf->gtp.pdrs_by_local_f_teid */ struct upf_gtp_dev *dev; struct upf_tunend desc; @@ -349,6 +351,7 @@ static int upf_gtp_tunend_destruct(struct upf_gtp_tunend *tun) { if (tun->active) upf_gtp_tunend_deactivate(tun); + hash_del(&tun->node_by_local_f_teid); llist_del(&tun->entry); return 0; } @@ -369,6 +372,7 @@ static struct upf_gtp_tunend *upf_gtp_tunend_alloc(struct upf_gtp_dev *dev, cons .dev = dev, .desc = *desc, }; + hash_add(dev->tunnels_by_local_f_teid, &tun->node_by_local_f_teid, tun->desc.access.local.teid); llist_add(&tun->entry, &dev->tunnels); talloc_set_destructor(tun, upf_gtp_tunend_destruct); return tun; @@ -425,7 +429,8 @@ static struct upf_gtp_tunend *upf_gtp_dev_tunend_find(struct upf_gtp_dev *dev, c { struct upf_gtp_tunend *tun; tunend_validate(tunend); - llist_for_each_entry(tun, &dev->tunnels, entry) { + + hash_for_each_possible(dev->tunnels_by_local_f_teid, tun, node_by_local_f_teid, tunend->access.local.teid) { if (upf_gtp_tunend_cmp(tunend, &tun->desc)) continue; return tun;