pespin submitted this change.
Optimize subscr_conns lookup
It was found that, on a busy osmo-bsc (>1000 concurrent calls spread over
several BTS), the CPU consumption looking up for gsm_subscriber_conn
based on SCCP conn_id can take a considerable amount of time (>5% of
osmo-bsc already taking 70% of the CPU time on the core it is running on).
The huge CPU consumption happens because a linear search is done (llist)
over the entire list of SCCP connections every time an SCCP message is
handled.
In order to optimize this lookup, this patch introduces a new struct
bsc_sccp_inst which becomes associated to the libosmo-sccp
osmo_sccp_instance. Each of this strucs maintains an rbtree of
gsm_subscriber_conn ordered by conn_id.
As a result algorithmic complexity adds O(log(N)) during insert, lookup
and delete of SCCP conns, but gets rid of O(N) previous lookup.
As a plus, finding a new conn_id now takes generally O(log(N)), while
before it used to take O(N).
Related: SYS#6200
Change-Id: I667d3ec1dad0ab7bc0fa4799d9611f3a914d07e5
---
M TODO-RELEASE
M include/osmocom/bsc/gsm_data.h
M src/osmo-bsc/bsc_sccp.c
M src/osmo-bsc/bsc_subscr_conn_fsm.c
M src/osmo-bsc/lb.c
M src/osmo-bsc/osmo_bsc_sigtran.c
6 files changed, 183 insertions(+), 101 deletions(-)
diff --git a/TODO-RELEASE b/TODO-RELEASE
index 285dc63..98023fc 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -12,3 +12,4 @@
osmo-bsc CTRL,VTY osmo_fsm instance IDs now use new dynamic timeslot names 'DYNAMIC_OSMOCOM' and 'DYNAMIC_IPACCESS'
libosmogsm >1.8.0 circuit switched data stuff (gsm0808_enc/dec_channel_type etc.)
libosmo-abis >1.4.0 osmo_ortp.h: add RTP_PT_CSDATA
+libosmo-sccp >1.7.0 osmo_sccp_{get,set}_priv()
\ No newline at end of file
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index cdf0f43..0c5b485 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -19,6 +19,8 @@
#include <osmocom/core/fsm.h>
#include <osmocom/core/tdef.h>
#include <osmocom/core/time_cc.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/linuxrbtree.h>
#include <osmocom/crypt/auth.h>
@@ -331,6 +333,9 @@
/* SCCP connection related */
struct bsc_msc_data *msc;
+ /* entry in (struct bsc_sccp_inst)->connections */
+ struct rb_node node;
+
/* Sigtran connection ID:
* if set: Range (0..SCCP_CONN_ID_MAX) (24 bit)
* if unset: SCCP_CONN_ID_UNSET (-1) if unset */
@@ -871,6 +876,19 @@
struct osmo_time_cc static_tch;
};
+struct bsc_sccp_inst {
+ struct osmo_sccp_instance *sccp; /* backpointer */
+ /* rbtree root of 'sstruct gsm_subscriber_connection' in this instance, ordered by conn_id */
+ struct rb_root connections;
+ uint32_t next_id; /* next id to allocate */
+};
+
+struct bsc_sccp_inst *bsc_sccp_inst_alloc(void *ctx);
+uint32_t bsc_sccp_inst_next_conn_id(struct bsc_sccp_inst *bsc_sccp);
+int bsc_sccp_inst_register_gscon(struct bsc_sccp_inst *bsc_sccp, struct gsm_subscriber_connection *conn);
+void bsc_sccp_inst_unregister_gscon(struct bsc_sccp_inst *bsc_sccp, struct gsm_subscriber_connection *conn);
+struct gsm_subscriber_connection *bsc_sccp_inst_get_gscon_by_conn_id(const struct bsc_sccp_inst *bsc_sccp, uint32_t conn_id);
+
struct gsm_network {
struct osmo_plmn_id plmn;
@@ -1030,8 +1048,6 @@
enum gsm48_rr_cause bsc_gsm48_rr_cause_from_gsm0808_cause(enum gsm0808_cause c);
enum gsm48_rr_cause bsc_gsm48_rr_cause_from_rsl_cause(uint8_t c);
-uint32_t bsc_sccp_inst_next_conn_id(struct osmo_sccp_instance *sccp);
-
/* Interference Measurement Parameters */
struct gsm_interf_meas_params {
/* Intave: Interference Averaging period (see 3GPP TS 45.008, table A.1) */
diff --git a/src/osmo-bsc/bsc_sccp.c b/src/osmo-bsc/bsc_sccp.c
index e0cce39..6fa1d4b 100644
--- a/src/osmo-bsc/bsc_sccp.c
+++ b/src/osmo-bsc/bsc_sccp.c
@@ -27,11 +27,82 @@
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/lb.h>
-/* We need an unused SCCP conn_id across all SCCP users. */
-uint32_t bsc_sccp_inst_next_conn_id(struct osmo_sccp_instance *sccp)
+struct bsc_sccp_inst *bsc_sccp_inst_alloc(void *ctx)
{
- static uint32_t next_id = 1;
- int i;
+ struct bsc_sccp_inst *bsc_sccp;
+
+ bsc_sccp = talloc_zero(ctx, struct bsc_sccp_inst);
+ OSMO_ASSERT(bsc_sccp);
+ bsc_sccp->next_id = 1;
+
+ return bsc_sccp;
+}
+
+int bsc_sccp_inst_register_gscon(struct bsc_sccp_inst *bsc_sccp, struct gsm_subscriber_connection *conn)
+{
+ struct rb_node **n = &(bsc_sccp->connections.rb_node);
+ struct rb_node *parent = NULL;
+ uint32_t conn_id = conn->sccp.conn_id;
+
+ OSMO_ASSERT(conn_id != SCCP_CONN_ID_UNSET);
+
+ while (*n) {
+ struct gsm_subscriber_connection *it;
+
+ it = container_of(*n, struct gsm_subscriber_connection, sccp.node);
+
+ parent = *n;
+ if (conn_id < it->sccp.conn_id) {
+ n = &((*n)->rb_left);
+ } else if (conn_id > it->sccp.conn_id) {
+ n = &((*n)->rb_right);
+ } else {
+ LOGP(DMSC, LOGL_ERROR,
+ "Trying to reserve already reserved conn_id %u\n", conn_id);
+ return -EEXIST;
+ }
+ }
+
+ rb_link_node(&conn->sccp.node, parent, n);
+ rb_insert_color(&conn->sccp.node, &bsc_sccp->connections);
+ return 0;
+}
+
+void bsc_sccp_inst_unregister_gscon(struct bsc_sccp_inst *bsc_sccp, struct gsm_subscriber_connection *conn)
+{
+ OSMO_ASSERT(conn->sccp.conn_id != SCCP_CONN_ID_UNSET);
+ rb_erase(&conn->sccp.node, &bsc_sccp->connections);
+}
+
+/* Helper function to Check if the given connection id is already assigned */
+struct gsm_subscriber_connection *bsc_sccp_inst_get_gscon_by_conn_id(const struct bsc_sccp_inst *bsc_sccp, uint32_t conn_id)
+{
+ const struct rb_node *node = bsc_sccp->connections.rb_node;
+ struct gsm_subscriber_connection *conn;
+
+ OSMO_ASSERT(conn_id != SCCP_CONN_ID_UNSET);
+ /* Range (0..SCCP_CONN_ID_MAX) expected, see bsc_sccp_inst_next_conn_id() */
+ OSMO_ASSERT(conn_id <= SCCP_CONN_ID_MAX);
+
+ while (node) {
+ conn = container_of(node, struct gsm_subscriber_connection, sccp.node);
+ if (conn_id < conn->sccp.conn_id)
+ node = node->rb_left;
+ else if (conn_id > conn->sccp.conn_id)
+ node = node->rb_right;
+ else
+ return conn;
+ }
+
+ return NULL;
+}
+
+/* We need an unused SCCP conn_id across all SCCP users. */
+uint32_t bsc_sccp_inst_next_conn_id(struct bsc_sccp_inst *bsc_sccp)
+{
+ uint32_t first_id, test_id;
+
+ first_id = test_id = bsc_sccp->next_id;
/* SUA: RFC3868 sec 3.10.4:
* The source reference number is a 4 octet long integer.
@@ -41,59 +112,26 @@
* reference number which is generated and used by the local node to identify the
* connection section after the connection section is set up.
* The coding "all ones" is reserved for future use.
- * Hence, let's simply use 24 bit ids to fit all link types (excluding 0x00ffffff).
+ *Hence, as we currently use the connection ID also as local reference,
+ *let's simply use 24 bit ids to fit all link types (excluding 0x00ffffff).
*/
- /* 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;
- bool conn_id_already_used = false;
-
+ while (bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, test_id)) {
/* 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;
+ test_id = (test_id + 1) & 0x00FFFFFF;
+ if (OSMO_UNLIKELY(test_id == 0x00FFFFFF))
+ test_id = 0;
- llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) {
- if (conn->sccp.msc && conn->sccp.msc->a.sccp == sccp &&
- conn->sccp.conn_id == conn_id) {
- conn_id_already_used = true;
- break;
- }
- }
-
- if (!conn_id_already_used)
- return conn_id;
+ /* Did a whole loop, all used, fail */
+ if (OSMO_UNLIKELY(test_id == first_id))
+ return SCCP_CONN_ID_UNSET;
}
- return SCCP_CONN_ID_UNSET;
+
+ bsc_sccp->next_id = test_id;
+ /* Optimized modulo operation (% SCCP_CONN_ID_MAX) using bitwise AND plus CMP: */
+ bsc_sccp->next_id = (bsc_sccp->next_id + 1) & 0x00FFFFFF;
+ if (OSMO_UNLIKELY(bsc_sccp->next_id == 0x00FFFFFF))
+ bsc_sccp->next_id = 0;
+
+ return test_id;
}
diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c
index e37f030..8e21992 100644
--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c
+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c
@@ -1111,6 +1111,11 @@
osmo_sccp_tx_disconn(msc->a.sccp_user, conn->sccp.conn_id, &msc->a.bsc_addr, 0);
conn->sccp.state = SUBSCR_SCCP_ST_NONE;
}
+ if (conn->sccp.conn_id != SCCP_CONN_ID_UNSET && conn->sccp.msc) {
+ struct bsc_sccp_inst *bsc_sccp = osmo_sccp_get_priv(conn->sccp.msc->a.sccp);
+ bsc_sccp_inst_unregister_gscon(bsc_sccp, conn);
+ conn->sccp.conn_id = SCCP_CONN_ID_UNSET;
+ }
if (conn->bsub) {
LOGPFSML(fi, LOGL_DEBUG, "Putting bsc_subscr\n");
diff --git a/src/osmo-bsc/lb.c b/src/osmo-bsc/lb.c
index 6e2d074..6c6f599 100644
--- a/src/osmo-bsc/lb.c
+++ b/src/osmo-bsc/lb.c
@@ -31,22 +31,7 @@
#include <osmocom/bsc/osmo_bsc_sigtran.h>
#include <osmocom/bsc/lcs_loc_req.h>
#include <osmocom/bsc/bssmap_reset.h>
-
-static struct gsm_subscriber_connection *get_bsc_conn_by_lb_conn_id(uint32_t conn_id)
-{
- struct gsm_subscriber_connection *conn;
-
- /* Range (0..SCCP_CONN_ID_MAX) expected, see bsc_sccp_inst_next_conn_id() */
- OSMO_ASSERT(conn_id <= SCCP_CONN_ID_MAX);
-
- 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)
- return conn;
- }
-
- return NULL;
-}
+#include <osmocom/bsc/gsm_data.h>
/* Send reset to SMLC */
int bssmap_le_tx_reset(void)
@@ -150,6 +135,8 @@
{
struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
struct osmo_sccp_user *scu = _scu;
+ struct osmo_sccp_instance *sccp = osmo_sccp_get_sccp(scu);
+ struct bsc_sccp_inst *bsc_sccp = osmo_sccp_get_priv(sccp);
struct gsm_subscriber_connection *conn;
int rc = 0;
@@ -172,7 +159,7 @@
case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_CONFIRM):
/* Handle inbound confirmation of outbound connection */
DEBUGP(DLCS, "N-CONNECT.cnf(%u)\n", scu_prim->u.connect.conn_id);
- conn = get_bsc_conn_by_lb_conn_id(scu_prim->u.connect.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.connect.conn_id);
if (conn) {
conn->lcs.lb.state = SUBSCR_SCCP_ST_CONNECTED;
if (msgb_l2len(oph->msg) > 0) {
@@ -188,7 +175,7 @@
/* Handle incoming connection oriented data */
DEBUGP(DLCS, "N-DATA.ind(%u)\n", scu_prim->u.data.conn_id);
- conn = get_bsc_conn_by_lb_conn_id(scu_prim->u.data.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.data.conn_id);
if (!conn) {
LOGP(DLCS, LOGL_ERROR, "N-DATA.ind(%u) for unknown conn_id\n", scu_prim->u.data.conn_id);
rc = -EINVAL;
@@ -206,7 +193,7 @@
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)),
scu_prim->u.disconnect.cause);
/* indication of disconnect */
- conn = get_bsc_conn_by_lb_conn_id(scu_prim->u.disconnect.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.disconnect.conn_id);
if (!conn) {
LOGP(DLCS, LOGL_ERROR, "N-DISCONNECT.ind for unknown conn_id %u\n",
scu_prim->u.disconnect.conn_id);
@@ -234,6 +221,7 @@
struct osmo_ss7_instance *ss7;
uint32_t conn_id;
int rc;
+ struct bsc_sccp_inst *bsc_sccp = osmo_sccp_get_priv(bsc_gsmnet->smlc->sccp);
OSMO_ASSERT(conn);
OSMO_ASSERT(msg);
@@ -244,7 +232,7 @@
return -EINVAL;
}
- conn_id = bsc_sccp_inst_next_conn_id(bsc_gsmnet->smlc->sccp);
+ conn_id = bsc_sccp_inst_next_conn_id(bsc_sccp);
if (conn_id == SCCP_CONN_ID_UNSET) {
LOGPFSMSL(conn->fi, DLCS, LOGL_ERROR, "Unable to allocate SCCP Connection ID for BSSMAP-LE to SMLC\n");
return -ENOSPC;
@@ -421,6 +409,7 @@
enum osmo_ss7_asp_protocol used_proto = OSMO_SS7_ASP_PROT_M3UA;
char inst_name[32];
const char *smlc_name = "smlc";
+ struct bsc_sccp_inst *bsc_sccp;
/* Already set up? */
if (bsc_gsmnet->smlc->sccp_user)
@@ -454,6 +443,9 @@
if (!sccp)
return -EINVAL;
bsc_gsmnet->smlc->sccp = sccp;
+ bsc_sccp = bsc_sccp_inst_alloc(tall_bsc_ctx);
+ bsc_sccp->sccp = sccp;
+ osmo_sccp_set_priv(sccp, bsc_sccp);
/* If unset, use default local SCCP address */
if (!bsc_gsmnet->smlc->bsc_addr.presence)
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
index 973832b..830b72e 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -45,26 +45,6 @@
#define DEFAULT_ASP_LOCAL_IP "localhost"
#define DEFAULT_ASP_REMOTE_IP "localhost"
-/* Helper function to Check if the given connection id is already assigned */
-static struct gsm_subscriber_connection *get_bsc_conn_by_conn_id(const struct osmo_sccp_user *scu, uint32_t conn_id)
-{
- struct gsm_subscriber_connection *conn;
- const struct osmo_sccp_instance *sccp = osmo_sccp_get_sccp(scu);
-
- /* Range (0..SCCP_CONN_ID_MAX) expected, see bsc_sccp_inst_next_conn_id() */
- OSMO_ASSERT(conn_id <= SCCP_CONN_ID_MAX);
-
- llist_for_each_entry(conn, &bsc_gsmnet->subscr_conns, entry) {
- if (conn->sccp.msc && conn->sccp.msc->a.sccp != sccp)
- continue;
- if (conn->sccp.conn_id != conn_id)
- continue;
- return conn;
- }
-
- return NULL;
-}
-
struct gsm_subscriber_connection *bsc_conn_by_bsub(const struct bsc_subscr *bsub)
{
struct gsm_subscriber_connection *conn;
@@ -170,10 +150,12 @@
static int handle_n_connect_from_msc(struct osmo_sccp_user *scu, struct osmo_scu_prim *scu_prim)
{
struct bsc_msc_data *msc = get_msc_by_addr(&scu_prim->u.connect.calling_addr);
+ struct osmo_sccp_instance *sccp = osmo_sccp_get_sccp(scu);
+ struct bsc_sccp_inst *bsc_sccp = osmo_sccp_get_priv(sccp);
struct gsm_subscriber_connection *conn;
int rc = 0;
- conn = get_bsc_conn_by_conn_id(scu, scu_prim->u.connect.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.connect.conn_id);
if (conn) {
LOGP(DMSC, LOGL_NOTICE,
"(calling_addr=%s conn_id=%u) N-CONNECT.ind with already used conn_id, ignoring\n",
@@ -202,6 +184,13 @@
return -ENOMEM;
conn->sccp.msc = msc;
conn->sccp.conn_id = scu_prim->u.connect.conn_id;
+ if (bsc_sccp_inst_register_gscon(bsc_sccp, conn) < 0) {
+ LOGP(DMSC, LOGL_NOTICE, "(calling_addr=%s conn_id=%u) N-CONNECT.ind failed registering conn\n",
+ osmo_sccp_addr_dump(&scu_prim->u.connect.calling_addr), scu_prim->u.connect.conn_id);
+ osmo_fsm_inst_term(conn->fi, OSMO_FSM_TERM_REQUEST, NULL);
+ rc = -ENOENT;
+ goto refuse;
+ }
/* Take actions asked for by the enclosed PDU */
osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_IND, scu_prim);
@@ -217,6 +206,8 @@
{
struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
struct osmo_sccp_user *scu = _scu;
+ struct osmo_sccp_instance *sccp = osmo_sccp_get_sccp(scu);
+ struct bsc_sccp_inst *bsc_sccp = osmo_sccp_get_priv(sccp);
struct gsm_subscriber_connection *conn;
int rc = 0;
@@ -237,7 +228,7 @@
/* Handle outbound connection confirmation */
DEBUGP(DMSC, "N-CONNECT.cnf(%u, %s)\n", scu_prim->u.connect.conn_id,
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
- conn = get_bsc_conn_by_conn_id(scu, scu_prim->u.connect.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.connect.conn_id);
if (conn) {
osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_A_CONN_CFM, scu_prim);
conn->sccp.state = SUBSCR_SCCP_ST_CONNECTED;
@@ -256,7 +247,7 @@
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
/* Incoming data is a sign of a vital connection */
- conn = get_bsc_conn_by_conn_id(scu, scu_prim->u.data.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.data.conn_id);
if (conn) {
a_reset_conn_success(conn->sccp.msc);
handle_data_from_msc(conn, oph->msg);
@@ -268,7 +259,7 @@
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)),
scu_prim->u.disconnect.cause);
/* indication of disconnect */
- conn = get_bsc_conn_by_conn_id(scu, scu_prim->u.disconnect.conn_id);
+ conn = bsc_sccp_inst_get_gscon_by_conn_id(bsc_sccp, scu_prim->u.disconnect.conn_id);
if (conn) {
conn->sccp.state = SUBSCR_SCCP_ST_NONE;
if (msgb_l2len(oph->msg) > 0)
@@ -323,6 +314,7 @@
{
struct osmo_ss7_instance *ss7;
struct bsc_msc_data *msc;
+ struct bsc_sccp_inst *bsc_sccp;
uint32_t conn_id;
int rc;
@@ -338,11 +330,16 @@
return -EINVAL;
}
- conn->sccp.conn_id = conn_id = bsc_sccp_inst_next_conn_id(conn->sccp.msc->a.sccp);
+ bsc_sccp = osmo_sccp_get_priv(msc->a.sccp);
+ conn->sccp.conn_id = conn_id = bsc_sccp_inst_next_conn_id(bsc_sccp);
if (conn->sccp.conn_id == SCCP_CONN_ID_UNSET) {
LOGP(DMSC, LOGL_ERROR, "Unable to allocate SCCP Connection ID\n");
return -1;
}
+ if (bsc_sccp_inst_register_gscon(bsc_sccp, conn) < 0) {
+ LOGP(DMSC, LOGL_ERROR, "Unable to register SCCP connection (id=%u)\n", conn->sccp.conn_id);
+ return -1;
+ }
LOGP(DMSC, LOGL_DEBUG, "Allocated new connection id: %u\n", conn->sccp.conn_id);
ss7 = osmo_ss7_instance_find(msc->a.cs7_instance);
OSMO_ASSERT(ss7);
@@ -520,6 +517,7 @@
int prev_msc_nr;
struct osmo_sccp_instance *sccp;
+ struct bsc_sccp_inst *bsc_sccp;
llist_for_each_entry(msc, msc_list, entry) {
/* An MSC with invalid cs7 instance id defaults to cs7 instance 0 */
@@ -563,6 +561,10 @@
if (!sccp)
return -EINVAL;
+ bsc_sccp = bsc_sccp_inst_alloc(tall_bsc_ctx);
+ bsc_sccp->sccp = sccp;
+ osmo_sccp_set_priv(sccp, bsc_sccp);
+
/* Now that the SCCP client is set up, configure all MSCs on this cs7 instance to use it */
llist_for_each_entry(msc, msc_list, entry) {
char msc_name[32];
To view, visit change 31866. To unsubscribe, or for help writing mail filters, visit settings.