diff --git a/include/osmocom/msc/transaction.h b/include/osmocom/msc/transaction.h index 928b137ae..499a29412 100644 --- a/include/osmocom/msc/transaction.h +++ b/include/osmocom/msc/transaction.h @@ -132,6 +132,8 @@ struct gsm_trans { struct gsm_trans *peer; enum bridge_state state; } bridge; + //struct osmo_lcls lcls; + struct osmo_lcls *lcls; }; diff --git a/src/libmsc/gsm_04_08_cc.c b/src/libmsc/gsm_04_08_cc.c index ed29e8494..e950f0857 100644 --- a/src/libmsc/gsm_04_08_cc.c +++ b/src/libmsc/gsm_04_08_cc.c @@ -485,6 +485,70 @@ static void gsm48_start_cc_timer(struct gsm_trans *trans, int current, trans->cc.Tcurrent = current; } +struct osmo_lcls *lcls_compose(struct osmo_lcls *lcls_fixme_for_member, 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) + 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; + } + + /* Why this test? Do we need it? Where to find conn now, if this is still valid? + if (!cc_trans->conn) { + 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_store32be(0, 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)); + + return lcls; +} + static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) { struct gsm48_hdr *gh = msgb_l3(msg); @@ -498,6 +562,11 @@ static int gsm48_cc_rx_setup(struct gsm_trans *trans, struct msgb *msg) memset(&setup, 0, sizeof(struct gsm_mncc)); setup.callref = trans->callref; + /* New Global Call Reference */ + trans->lcls = lcls_compose(trans->lcls, trans, true); + //if (lcls_compose(&trans-lcls, trans, true) + // LOG_TRANS(trans, LOGL_ERROR, "LCLS Error\n"); + tlv_parse(&tp, &gsm48_att_tlvdef, gh->data, payload_len, 0, 0); /* emergency setup is identified by msg_type */ if (msg_type == GSM48_MT_CC_EMERG_SETUP) { @@ -1856,6 +1925,9 @@ static int mncc_tx_to_gsm_cc(struct gsm_network *net, const union mncc_msg *msg) /* Find callref */ trans = trans_find_by_callref(net, data->callref); + if (trans) + LOG_TRANS(trans, LOGL_ERROR, "CC MNCC TX trans->lcls %s\n", osmo_gcr_dump(trans->lcls)); + /* Callref unknown */ if (!trans) { struct vlr_subscr *vsub; @@ -2145,6 +2217,8 @@ int gsm0408_rcv_cc(struct msc_a *msc_a, struct msgb *msg) /* Find transaction */ trans = trans_find_by_id(msc_a, TRANS_CC, transaction_id); + if (trans) + LOG_TRANS(trans, LOGL_ERROR, "RCV_CC trans->lcls %s\n", osmo_gcr_dump(trans->lcls)); /* Create transaction */ if (!trans) { diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c index 8583154d9..ac9a32d94 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -517,7 +517,7 @@ static void msc_a_fsm_authenticated(struct osmo_fsm_inst *fi, uint32_t event, vo } } -struct osmo_lcls *lcls_compose(const struct msc_a *msc_a, struct gsm_trans *cc_trans, bool use_lac) +struct osmo_lcls *lcls_compose2(const struct msc_a *msc_a, struct gsm_trans *cc_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? @@ -564,6 +564,7 @@ struct osmo_lcls *lcls_compose(const struct msc_a *msc_a, struct gsm_trans *cc_t osmo_plmn_to_bcd(lcls->gcr.net, &cc_trans->net->plmn); osmo_store32be(cc_trans->callref, lcls->gcr.cr); + //osmo_store32be(0, lcls->gcr.cr); osmo_store16be(use_lac ? msc_a->via_cell.lai.lac : 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", @@ -602,6 +603,15 @@ static void msc_a_call_leg_ran_local_addr_available(struct msc_a *msc_a) return; } + if (cc_trans->lcls) { + LOG_MSC_A(msc_a, LOGL_ERROR, "We already have LCLS GCR: %s\n", osmo_gcr_dump(cc_trans->lcls)); + + } else { + /* Pass what here??? DATA_WE_NEED, bool use_lac */ + LOG_MSC_A(msc_a, LOGL_ERROR, "We don't have LCLS GCR: %s\n", osmo_gcr_dump(cc_trans->lcls)); + //cc_trans->lcls = lcls_compose(msc_a, cc_trans, true); + } + /* The RAN side RTP address is known, so the voice Assignment can commence. */ msg = (struct ran_msg){ .msg_type = RAN_MSG_ASSIGNMENT_COMMAND, @@ -612,8 +622,7 @@ 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, - /* Pass what here??? DATA_WE_NEED, bool use_lac */ - .lcls = lcls_compose(msc_a, cc_trans, true), + .lcls = cc_trans->lcls, }, }; @@ -1628,6 +1637,9 @@ int msc_a_ran_decode_cb(struct osmo_fsm_inst *msc_a_fi, void *data, const struct d->ran_dec = msg; + if (msg->assignment_command.lcls) + LOG_MSC_A(msc_a, LOGL_ERROR, "Found Some LCLS in decode"); + switch (d->from_role) { case MSC_ROLE_I: LOG_MSC_A(msc_a, LOGL_DEBUG, "RAN decode: %s\n", msg->msg_name ? : ran_msg_type_name(msg->msg_type)); @@ -1671,6 +1683,9 @@ int _msc_a_msg_down(struct msc_a *msc_a, enum msc_role to_role, uint32_t to_role .msg = msc_role_ran_encode(msc_a->c.fi, ran_msg), }; int rc; + /* We've lost the LCLS here + or it's encoded in the msg???? + */ if (!an_apdu.msg) return -EIO; rc = _msub_role_dispatch(msc_a->c.msub, to_role, to_role_event, &an_apdu, file, line); diff --git a/src/libmsc/msub.c b/src/libmsc/msub.c index 112703a13..4b003e3f1 100644 --- a/src/libmsc/msub.c +++ b/src/libmsc/msub.c @@ -546,6 +546,10 @@ void msc_role_forget_conn(struct osmo_fsm_inst *role, struct ran_conn *conn) struct msgb *msc_role_ran_encode(struct osmo_fsm_inst *fi, const struct ran_msg *ran_msg) { + if (ran_msg->assignment_command.lcls) { + LOGPFSML(fi, LOGL_ERROR, "Have LCLS info....\n"); + } + struct msc_role_common *c = fi->priv; struct msgb *msg; if (!c->ran->ran_encode) { @@ -553,6 +557,7 @@ struct msgb *msc_role_ran_encode(struct osmo_fsm_inst *fi, const struct ran_msg ran_msg_type_name(ran_msg->msg_type), osmo_rat_type_name(c->ran->type)); return NULL; } + /* ran_a_encode ran_msg_a.c Line 1252 */ msg = c->ran->ran_encode(fi, ran_msg); if (!msg) LOGPFSML(fi, LOGL_ERROR, "Failed to encode %s\n", ran_msg_type_name(ran_msg->msg_type)); @@ -586,5 +591,6 @@ int msc_role_ran_decode(struct osmo_fsm_inst *fi, const struct an_apdu *an_apdu, osmo_rat_type_name(c->ran->type)); return -ENOTSUP; } + /* ran_a_decode_l2 */ return c->ran->ran_dec_l2(&ran_dec, an_apdu->msg); } diff --git a/src/libmsc/ran_msg_a.c b/src/libmsc/ran_msg_a.c index 87e0a8b39..05966b28f 100644 --- a/src/libmsc/ran_msg_a.c +++ b/src/libmsc/ran_msg_a.c @@ -1251,11 +1251,21 @@ static struct msgb *_ran_a_encode(struct osmo_fsm_inst *caller_fi, const struct struct msgb *ran_a_encode(struct osmo_fsm_inst *caller_fi, const struct ran_msg *ran_enc_msg) { + /* This msgb is what will end up down stream in CC */ + if (ran_enc_msg->assignment_command.lcls) { + LOG_RAN_A_ENC(caller_fi, LOGL_ERROR, "Have got LCLS info to put into msgb......"); + } + + /* this is going to call the ass2() thing */ + struct msgb *msg = _ran_a_encode(caller_fi, ran_enc_msg); if (!msg) return NULL; + + /* msg should contain our lcls! */ + msg->l2h = msg->data; /* some consistency checks to ensure we don't send invalid length */