diff options
author | Pau Espin Pedrol <pespin@sysmocom.de> | 2023-03-09 14:06:21 +0100 |
---|---|---|
committer | Pau Espin Pedrol <pespin@sysmocom.de> | 2023-03-13 11:58:49 +0100 |
commit | 53cd4ad5fcbfda93644feb85beb64256f1cd5d31 (patch) | |
tree | bdf1e50fb0a16080aaa860e1c0fe8a4f1141594a | |
parent | 8958269ea9cffe7ace6bd57a860606cd651cd46c (diff) |
bscc_sccp: Small optimiztion in bsc_sccp_inst_next_conn_id()
Refactor the double loop to check a code path matching the sccp_instance
once instead of doing so for every subscr_conn.
If for instance let's say we have 1000 concurrent calls in progress,
which means we have 1000 subscr_conn, which means we at least do the
extra check regarding SMLC vs MSC 1000 times (at least, xN times if N
conn_id already used are already found).
That overhead happens every time a new subscr_conn is created (which in
a BSC with already 1000 concurrent calls can potentially happen quite
frequently).
Change-Id: Ic32b1eeb201fc51110e1ee130110824845f81e82
-rw-r--r-- | src/osmo-bsc/bsc_sccp.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/src/osmo-bsc/bsc_sccp.c b/src/osmo-bsc/bsc_sccp.c index 431e194f8..e0cce39bf 100644 --- a/src/osmo-bsc/bsc_sccp.c +++ b/src/osmo-bsc/bsc_sccp.c @@ -47,6 +47,33 @@ uint32_t bsc_sccp_inst_next_conn_id(struct osmo_sccp_instance *sccp) /* This looks really suboptimal, but in most cases the static next_id should indicate exactly the next unused * conn_id, and we only iterate all conns once to make super sure that it is not already in use. */ + /* SCCP towards SMLC: */ + if (bsc_gsmnet->smlc->sccp == sccp) { + for (i = 0; i < SCCP_CONN_ID_MAX; i++) { + struct gsm_subscriber_connection *conn; + uint32_t conn_id = next_id; + bool conn_id_already_used = false; + + /* Optimized modulo operation (% SCCP_CONN_ID_MAX) using bitwise AND plus CMP: */ + next_id = (next_id + 1) & 0x00FFFFFF; + if (OSMO_UNLIKELY(next_id == 0x00FFFFFF)) + next_id = 0; + + llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) { + if (conn->lcs.lb.state != SUBSCR_SCCP_ST_NONE && + conn->lcs.lb.conn_id == conn_id) { + conn_id_already_used = true; + break; + } + } + + if (!conn_id_already_used) + return conn_id; + } + return 0xFFFFFFFF; + } + + /* SCCP towards MSC: */ for (i = 0; i < SCCP_CONN_ID_MAX; i++) { struct gsm_subscriber_connection *conn; uint32_t conn_id = next_id; @@ -58,19 +85,10 @@ uint32_t bsc_sccp_inst_next_conn_id(struct osmo_sccp_instance *sccp) next_id = 0; llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) { - if (conn->sccp.msc && conn->sccp.msc->a.sccp == sccp) { - if (conn_id == conn->sccp.conn_id) { - conn_id_already_used = true; - break; - } - } - - if (bsc_gsmnet->smlc->sccp == sccp - && conn->lcs.lb.state != SUBSCR_SCCP_ST_NONE) { - if (conn_id == conn->lcs.lb.conn_id) { - conn_id_already_used = true; - break; - } + if (conn->sccp.msc && conn->sccp.msc->a.sccp == sccp && + conn->sccp.conn_id == conn_id) { + conn_id_already_used = true; + break; } } |