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 <[email protected]>
Gerrit-MessageType: newchange

Reply via email to