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: I667d3ec1dad0ab7bc0fa4799d9611f3a914d07e5changes/66/31866/3
parent
9c21dc3d16
commit
85062ccad3
|
@ -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()
|
|
@ -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 @@ struct gsm_subscriber_connection {
|
|||
/* 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 all_allocated {
|
|||
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 gsm_phys_chan_config gsm_pchan_by_lchan_type(enum gsm_chan_t type);
|
|||
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) */
|
||||
|
|
|
@ -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 @@ uint32_t bsc_sccp_inst_next_conn_id(struct osmo_sccp_instance *sccp)
|
|||
* 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;
|
||||
}
|
||||
|
|
|
@ -1111,6 +1111,11 @@ static void gscon_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cau
|
|||
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");
|
||||
|
|
|
@ -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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
{
|
||||
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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
/* 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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
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 @@ static int lb_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg
|
|||
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 @@ static int lb_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg
|
|||
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 @@ static int lb_start(void)
|
|||
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 @@ static int lb_start(void)
|
|||
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)
|
||||
|
|
|
@ -45,26 +45,6 @@ static struct llist_head *msc_list;
|
|||
#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_unitdata_from_msc(const struct osmo_sccp_addr *msc_addr, struc
|
|||
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 @@ static int handle_n_connect_from_msc(struct osmo_sccp_user *scu, struct osmo_scu
|
|||
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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
{
|
||||
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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
/* 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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
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 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
|
|||
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 @@ __attribute__((weak)) int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_conne
|
|||
{
|
||||
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 @@ __attribute__((weak)) int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_conne
|
|||
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 osmo_bsc_sigtran_init(struct llist_head *mscs)
|
|||
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 @@ int osmo_bsc_sigtran_init(struct llist_head *mscs)
|
|||
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];
|
||||
|
|
Loading…
Reference in New Issue