From ba8fe4e43565896773a9ce2cd00084c6fdd924f3 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 12 Mar 2019 16:40:07 +0100 Subject: Autofill LCLS parameters for A-interface transactions That's experimental patch to facilitate testing of BSC implementation of LCLS. Change-Id: I35ae6b6ca04925c8d300bc1a0269af00eac727f3 --- include/osmocom/msc/debug.h | 1 + include/osmocom/msc/mncc.h | 3 ++ include/osmocom/msc/ran_msg.h | 1 + include/osmocom/msc/transaction.h | 3 ++ include/osmocom/msc/vlr.h | 1 + src/libmsc/msc_a.c | 10 ++++++ src/libmsc/ran_msg_a.c | 3 +- src/libmsc/transaction.c | 69 +++++++++++++++++++++++++++++++++++++++ src/libvlr/vlr.c | 1 + 9 files changed, 91 insertions(+), 1 deletion(-) diff --git a/include/osmocom/msc/debug.h b/include/osmocom/msc/debug.h index 3347e20d4..0d08ceb11 100644 --- a/include/osmocom/msc/debug.h +++ b/include/osmocom/msc/debug.h @@ -8,6 +8,7 @@ enum { DCC, DMM, DRR, + DLCLS, DMNCC, DPAG, DMSC, diff --git a/include/osmocom/msc/mncc.h b/include/osmocom/msc/mncc.h index 1c8aff0c9..076747547 100644 --- a/include/osmocom/msc/mncc.h +++ b/include/osmocom/msc/mncc.h @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -161,6 +162,8 @@ struct gsm_mncc { unsigned char lchan_type; unsigned char lchan_mode; + struct osmo_gcr_parsed gcr; + /* A buffer to contain SDP ('\0' terminated) */ char sdp[1024]; }; diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h index 3b08b466c..5fdb90cda 100644 --- a/include/osmocom/msc/ran_msg.h +++ b/include/osmocom/msc/ran_msg.h @@ -88,6 +88,7 @@ struct ran_assignment_command { uint8_t osmux_cid; bool call_id_present; uint32_t call_id; + struct osmo_lcls *lcls; }; struct ran_cipher_mode_command { diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 928b137ae..494ad88db 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -132,6 +132,7 @@ struct gsm_trans { struct gsm_trans *peer; enum bridge_state state; } bridge; + struct osmo_lcls *lcls; }; @@ -145,6 +146,8 @@ struct gsm_trans *trans_find_by_sm_rp_mr(const struct gsm_network *net, const struct vlr_subscr *vsub, uint8_t sm_rp_mr); +struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac); + struct gsm_trans *trans_alloc(struct gsm_network *net, struct vlr_subscr *vsub, enum trans_type type, uint8_t trans_id, diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h index 3b9bbc41c..971db528b 100644 --- a/include/osmocom/msc/vlr.h +++ b/include/osmocom/msc/vlr.h @@ -271,6 +271,7 @@ struct vlr_instance { bool is_ps; uint8_t nri_bitlen; struct osmo_nri_ranges *nri_ranges; + bool lcls_enable; } cfg; /* A free-form pointer for use by the caller */ void *user_ctx; diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c index 0645c5434..765a2dc3f 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -517,6 +517,7 @@ static void msc_a_fsm_authenticated(struct osmo_fsm_inst *fi, uint32_t event, vo } } + /* The MGW has given us a local IP address for the RAN side. Ready to start the Assignment of a voice channel. */ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) { @@ -549,8 +550,10 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) .osmux_cid = msc_a->cc.call_leg->rtp[RTP_TO_RAN]->local_osmux_cid, .call_id_present = true, .call_id = cc_trans->callref, + .lcls = cc_trans->lcls, }, }; + if (msc_a_ran_down(msc_a, MSC_ROLE_I, &msg)) { LOG_MSC_A(msc_a, LOGL_ERROR, "Cannot send Assignment\n"); trans_free(cc_trans); @@ -1484,6 +1487,13 @@ int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d) rc = msc_a_up_ho(msc_a, d, MSC_HO_EV_RX_FAILURE); break; + case RAN_MSG_LCLS_STATUS: + /* The BSS sends us LCLS_STATUS. We do nothing for now, but it is not an error. */ + LOG_MSC_A(msc_a, LOGL_DEBUG, "LCLS_STATUS (%s) received from MSC-I\n", + gsm0808_lcls_status_name(msg->lcls_status.status)); + rc = 0; + break; + default: LOG_MSC_A(msc_a, LOGL_ERROR, "Message from MSC-I not implemented: %s\n", ran_msg_type_name(msg->msg_type)); rc = -ENOTSUP; diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c index 6a3370443..87e0a8b39 100644 --- a/src/libmsc/ran_msg_a.c +++ b/src/libmsc/ran_msg_a.c @@ -997,7 +997,8 @@ static struct msgb *ran_a_make_assignment_command(struct osmo_fsm_inst *log_fi, if(ac->call_id_present == true) call_id = &ac->call_id; - msg = gsm0808_create_ass(ac->channel_type, NULL, use_rtp_addr, use_scl, call_id); + msg = gsm0808_create_ass2(ac->channel_type, NULL, use_rtp_addr, use_scl, call_id, + NULL, ac->lcls); if (ac->osmux_present) _gsm0808_assignment_extend_osmux(msg, ac->osmux_cid); return msg; diff --git a/src/libmsc/transaction.c b/src/libmsc/transaction.c index 94712cc89..64bef8609 100644 --- a/src/libmsc/transaction.c +++ b/src/libmsc/transaction.c @@ -110,6 +110,75 @@ struct gsm_trans *trans_find_by_sm_rp_mr(const struct gsm_network *net, return NULL; } +struct osmo_lcls *trans_lcls_compose(const struct gsm_trans *trans, bool use_lac) +{ + /* FIXME: ensure that a interface is in use for this transaction + This fails test #13 because we have no sccp there Do we need this logging? + Can we get primary_pc elsewhere? */ + if (!trans->net->a.sri->sccp) { + printf("but returning NULL\n"); + return NULL; + } + struct osmo_ss7_instance *ss7 = osmo_sccp_get_ss7(trans->net->a.sri->sccp); + struct osmo_lcls *lcls; + uint8_t w = osmo_ss7_pc_width(&ss7->cfg.pc_fmt); + + if (!trans) { + LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for unallocated transaction\n"); + return NULL; + } + + if (!trans->net->vlr->cfg.lcls_enable) { + LOGP(DCC, LOGL_NOTICE, "LCLS disabled globally\n"); + return NULL; + } + + if (!trans->msc_a) { + LOGP(DCC, LOGL_ERROR, "LCLS: unable to fill parameters for transaction without connection\n"); + return NULL; + } + + if (trans->msc_a->c.ran->type != OSMO_RAT_GERAN_A) { + LOGP(DCC, LOGL_ERROR, "LCLS: only A interface is supported at the moment\n"); + return NULL; + } + + lcls = talloc_zero(trans, struct osmo_lcls); + if (!lcls) { + LOGP(DCC, LOGL_ERROR, "LCLS: failed to allocate osmo_lcls\n"); + return NULL; + } + + LOGP(DCC, LOGL_INFO, "LCLS: using %u bits (%u bytes) for node ID\n", w, w / 8); + + lcls->gcr.net_len = 3; + lcls->gcr.node = ss7->cfg.primary_pc; + + /* net id from Q.1902.3 3-5 bytes, this function gives 3 bytes exactly */ + osmo_plmn_to_bcd(lcls->gcr.net, &trans->net->plmn); + + osmo_store32be(trans->callref, lcls->gcr.cr); + osmo_store16be(use_lac ? trans->msc_a->via_cell.lai.lac : trans->msc_a->via_cell.cell_identity, lcls->gcr.cr + 3); + + LOGP(DCC, LOGL_INFO, "LCLS: allocated %s-based CR-ID %s\n", use_lac ? "LAC" : "CI", + osmo_hexdump(lcls->gcr.cr, 5)); + + lcls->config = GSM0808_LCLS_CFG_BOTH_WAY; + lcls->control = GSM0808_LCLS_CSC_CONNECT; + lcls->corr_needed = true; + lcls->gcr_available = true; + + LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_lcls_dump(lcls)); + LOGP(DCC, LOGL_DEBUG, "Filled %s\n", osmo_gcr_dump(lcls)); + + printf("Filled %s\n", osmo_lcls_dump(lcls)); + printf("Filled %s\n", osmo_gcr_dump(lcls)); + + printf("LCLS compose returning%p\n", lcls); + + return lcls; +} + static const char *trans_vsub_use(enum trans_type type) { return get_value_string_or_null(trans_type_names, type) ? : "trans-type-unknown"; diff --git a/src/libvlr/vlr.c b/src/libvlr/vlr.c index 33d6331c0..c6ec5ef53 100644 --- a/src/libvlr/vlr.c +++ b/src/libvlr/vlr.c @@ -1258,6 +1258,7 @@ struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops) vlr->cfg.assign_tmsi = true; vlr->cfg.nri_bitlen = OSMO_NRI_BITLEN_DEFAULT; vlr->cfg.nri_ranges = osmo_nri_ranges_alloc(vlr); + vlr->cfg.lcls_enable = 1; /* reset shared timer definitions */ osmo_tdefs_reset(msc_tdefs_vlr); -- cgit v1.2.3