neels has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-upf/+/31485
)
Change subject: scale: faster lookup whether local TEID is in use
......................................................................
scale: faster lookup whether local TEID is in use
Keep a hash table of all local GTP TEID assigned: speed up handing out
new TEID to new GTP tunnels, for both tunend and tunmap.
Before this, whenever osmo-upf sets up a tunnel, it would have to
linearly iterate *all* peers x sessions x GTP tunnels to ensure that a
TEID is not already in use. Now we iterate only one hashtable bucket.
Scoping: technically, a TEID would be scoped by the local GTP IP
address. For simplicity, osmo-upf hands out each TEID only once, across
all local GTP IP addresses. This also helps when analysing pcaps.
Change-Id: I920bb14da434ac29fcd49d95d207081bacb3d661
---
M include/osmocom/upf/up_session.h
M include/osmocom/upf/upf.h
M src/osmo-upf/up_session.c
M src/osmo-upf/upf.c
4 files changed, 35 insertions(+), 24 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/85/31485/1
diff --git a/include/osmocom/upf/up_session.h b/include/osmocom/upf/up_session.h
index c424df9..d42254d 100644
--- a/include/osmocom/upf/up_session.h
+++ b/include/osmocom/upf/up_session.h
@@ -69,7 +69,7 @@
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);
+struct up_session *up_session_find_by_local_teid(uint32_t teid);
void up_session_set_msg_ctx(struct up_session *session, struct osmo_pfcp_msg *m);
@@ -101,6 +101,9 @@
bool active;
char *inactive_reason;
+
+ /* hashtable entry for g_upf->pdr_by_local_teid */
+ struct hlist_node node_by_local_teid;
};
int pdr_to_str_buf(char *buf, size_t buflen, const struct pdr *pdr);
diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h
index 0d43785..acf28e3 100644
--- a/include/osmocom/upf/upf.h
+++ b/include/osmocom/upf/upf.h
@@ -121,6 +121,7 @@
struct {
uint32_t next_local_teid_state;
+ DECLARE_HASHTABLE(pdr_by_local_teid, 6);
} gtp;
struct llist_head netinst;
diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c
index 593f131..4700675 100644
--- a/src/osmo-upf/up_session.c
+++ b/src/osmo-upf/up_session.c
@@ -377,6 +377,8 @@
static void pdr_del(struct pdr *pdr)
{
llist_del(&pdr->entry);
+ if (pdr->local_f_teid)
+ hlist_del(&pdr->node_by_local_teid);
talloc_free(pdr);
}
@@ -479,6 +481,7 @@
.local_f_teid_present = true,
.local_f_teid = *pdr->local_f_teid,
};
+ hash_add(g_upf->gtp.pdr_by_local_teid, &pdr->node_by_local_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,
@@ -1052,18 +1055,12 @@
return NULL;
}
-struct up_session *up_session_find_by_local_teid(struct up_peer *peer, uint32_t teid)
+struct up_session *up_session_find_by_local_teid(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;
- }
+ struct pdr *pdr;
+ hash_for_each_possible(g_upf->gtp.pdr_by_local_teid, pdr, node_by_local_teid, teid)
{
+ if (pdr->local_f_teid && teid == pdr->local_f_teid->fixed.teid)
+ return pdr->session;
}
return NULL;
}
diff --git a/src/osmo-upf/upf.c b/src/osmo-upf/upf.c
index 1e5e549..43b379c 100644
--- a/src/osmo-upf/upf.c
+++ b/src/osmo-upf/upf.c
@@ -68,6 +68,7 @@
INIT_LLIST_HEAD(&g_upf->netinst);
hash_init(g_upf->tunmap.nft_tun_by_chain_id);
+ hash_init(g_upf->gtp.pdr_by_local_teid);
}
int upf_pfcp_init(void)
@@ -122,17 +123,6 @@
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++;
@@ -146,7 +136,7 @@
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))
+ if (up_session_find_by_local_teid(next_teid))
continue;
return next_teid;
}
--
To view, visit
https://gerrit.osmocom.org/c/osmo-upf/+/31485
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-upf
Gerrit-Branch: master
Gerrit-Change-Id: I920bb14da434ac29fcd49d95d207081bacb3d661
Gerrit-Change-Number: 31485
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de>
Gerrit-MessageType: newchange