pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-upf/+/39578?usp=email )
Change subject: Introduce hashtable to look up session in endpoint by UP SEID ......................................................................
Introduce hashtable to look up session in endpoint by UP SEID
This is used every time a new PFCP session was being allocated. It allows looking up if a given UP SEID exists in any of the peers. Before this patch, iterating over tens/hundreds of UP peers on every session creation took 38% of a full CPU.
Change-Id: I617b405e59a3435a1c4912bf4161bc9e036754b4 --- M include/osmocom/upf/up_endpoint.h M include/osmocom/upf/up_session.h M src/osmo-upf/up_endpoint.c M src/osmo-upf/up_session.c 4 files changed, 14 insertions(+), 4 deletions(-)
Approvals: Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve fixeria: Looks good to me, approved
diff --git a/include/osmocom/upf/up_endpoint.h b/include/osmocom/upf/up_endpoint.h index ac240cd..2aed25a 100644 --- a/include/osmocom/upf/up_endpoint.h +++ b/include/osmocom/upf/up_endpoint.h @@ -24,6 +24,7 @@ #pragma once
#include <osmocom/core/linuxlist.h> +#include <osmocom/core/hashtable.h>
struct osmo_pfcp_msg; struct osmo_pfcp_endpoint; @@ -37,6 +38,10 @@
/* list of struct up_peer. */ struct llist_head peers; + /* hashtable of (struct up_session) with key up_seid. + * Allows quick access to sessions (and its endpoint as backpointer) + * with a given up_seid. */ + DECLARE_HASHTABLE(sessions_by_up_seid, 10);
uint64_t next_up_seid_state; }; diff --git a/include/osmocom/upf/up_session.h b/include/osmocom/upf/up_session.h index 3dc7bb1..a20ae06 100644 --- a/include/osmocom/upf/up_session.h +++ b/include/osmocom/upf/up_session.h @@ -45,6 +45,9 @@ struct hlist_node node_by_up_seid; struct hlist_node node_by_cp_seid;
+ /* item in up_endpoint->peers_by_up_seid: */ + struct hlist_node ep_node_by_up_seid; + struct osmo_fsm_inst *fi; /* backpointer */ struct up_peer *up_peer; diff --git a/src/osmo-upf/up_endpoint.c b/src/osmo-upf/up_endpoint.c index 34351a6..f400bdc 100644 --- a/src/osmo-upf/up_endpoint.c +++ b/src/osmo-upf/up_endpoint.c @@ -239,6 +239,7 @@ struct up_endpoint *up_ep; up_ep = talloc_zero(ctx, struct up_endpoint); INIT_LLIST_HEAD(&up_ep->peers); + hash_init(up_ep->sessions_by_up_seid);
cfg = (struct osmo_pfcp_endpoint_cfg){ .local_addr = *local_addr, @@ -263,10 +264,9 @@
static struct up_session *up_endpoint_find_session(struct up_endpoint *ep, uint64_t up_seid) { - struct up_peer *peer; - llist_for_each_entry(peer, &ep->peers, entry) { - struct up_session *session = up_session_find_by_up_seid(peer, up_seid); - if (session) + struct up_session *session; + hash_for_each_possible(ep->sessions_by_up_seid, session, ep_node_by_up_seid, up_seid) { + if (session->up_seid == up_seid) return session; } return NULL; diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c index 97c9367..a9bc7c3 100644 --- a/src/osmo-upf/up_session.c +++ b/src/osmo-upf/up_session.c @@ -885,6 +885,7 @@
up_session_clear_pdr_far(session);
+ hash_del(&session->ep_node_by_up_seid); hash_del(&session->node_by_up_seid); hash_del(&session->node_by_cp_seid); } @@ -1022,6 +1023,7 @@
hash_add(peer->sessions_by_up_seid, &session->node_by_up_seid, session->up_seid); hash_add(peer->sessions_by_cp_seid, &session->node_by_cp_seid, session->cp_f_seid.seid); + hash_add(peer->up_endpoint->sessions_by_up_seid, &session->ep_node_by_up_seid, session->up_seid); return session; }