Move the bulk of RR processing from MSC into BSC
RR Messages like STATUS, GPRS SUSPEND, HANDOVER COMPLETE/FAIL, ... should be processed on the BSC side of things, not on the MSC side. This is among other things required in preparation of intra-BSC hand-over support in osmo-bsc.
This commit is contained in:
parent
95e862cab4
commit
cf149eebb6
|
@ -69,4 +69,7 @@ struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
|
|||
void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
|
||||
const struct gsm_lchan *lchan);
|
||||
|
||||
void release_security_operation(struct gsm_subscriber_connection *conn);
|
||||
void allocate_security_operation(struct gsm_subscriber_connection *conn);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -438,24 +438,55 @@ static void handle_classmark_chg(struct gsm_subscriber_connection *conn,
|
|||
/* we must have a classmark3 */
|
||||
if (gh->data[cm2_len+1] != 0x20) {
|
||||
DEBUGPC(DRR, "ERR CM3 TAG\n");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
if (cm2_len > 3) {
|
||||
DEBUGPC(DRR, "CM2 too long!\n");
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
|
||||
cm3_len = gh->data[cm2_len+2];
|
||||
cm3 = &gh->data[cm2_len+3];
|
||||
if (cm3_len > 14) {
|
||||
DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
|
||||
return -EINVAL;
|
||||
return;
|
||||
}
|
||||
DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
|
||||
}
|
||||
api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
|
||||
}
|
||||
|
||||
/* Chapter 9.1.16 Handover complete */
|
||||
static void handle_rr_ho_compl(struct msgb *msg)
|
||||
{
|
||||
struct lchan_signal_data sig;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
||||
DEBUGP(DRR, "HANDOVER COMPLETE cause = %s\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
|
||||
sig.lchan = msg->lchan;
|
||||
sig.mr = NULL;
|
||||
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
|
||||
/* FIXME: release old channel */
|
||||
}
|
||||
|
||||
/* Chapter 9.1.17 Handover Failure */
|
||||
static void handle_rr_ho_fail(struct msgb *msg)
|
||||
{
|
||||
struct lchan_signal_data sig;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
||||
DEBUGP(DRR, "HANDOVER FAILED cause = %s\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
|
||||
sig.lchan = msg->lchan;
|
||||
sig.mr = NULL;
|
||||
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
|
||||
/* FIXME: release allocated new channel */
|
||||
}
|
||||
|
||||
|
||||
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
||||
uint8_t link_id, struct msgb *msg)
|
||||
{
|
||||
|
@ -471,12 +502,38 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
|||
|
||||
gh = msgb_l3(msg);
|
||||
pdisc = gh->proto_discr & 0x0f;
|
||||
|
||||
/* the idea is to handle all RR messages here, and only hand
|
||||
* MM/CC/SMS-CP/LCS up to the MSC. Some messages like PAGING
|
||||
* RESPONSE or CM SERVICE REQUEST will not be covered here, as
|
||||
* they are only possible in the first L3 message of each L2
|
||||
* channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()
|
||||
* will call api->compl_l3() for it */
|
||||
switch (pdisc) {
|
||||
case GSM48_PDISC_RR:
|
||||
switch (gh->msg_type) {
|
||||
case GSM48_MT_RR_GPRS_SUSP_REQ:
|
||||
DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
|
||||
break;
|
||||
case GSM48_MT_RR_STATUS:
|
||||
DEBUGP(DRR, "RR STATUS (cause: %s)\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
break;
|
||||
case GSM48_MT_RR_MEAS_REP:
|
||||
/* This shouldn't actually end up here, as RSL treats
|
||||
* L3 Info of 08.58 MEASUREMENT REPORT different by calling
|
||||
* directly into gsm48_parse_meas_rep */
|
||||
LOGP(LOGL_ERROR, DMEAS, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
|
||||
break;
|
||||
case GSM48_MT_RR_HANDO_COMPL:
|
||||
handle_rr_ho_compl(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_HANDO_FAIL:
|
||||
handle_rr_ho_fail(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_CIPH_M_COMPL:
|
||||
if (api->cipher_mode_compl)
|
||||
return api->cipher_mode_compl(conn, msg,
|
||||
api->cipher_mode_compl(conn, msg,
|
||||
conn->lchan->encr.alg_id);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_COMPL:
|
||||
|
@ -498,21 +555,25 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
|||
conn->lchan->encr.alg_id,
|
||||
chan_mode_to_speech(conn->lchan));
|
||||
}
|
||||
return;
|
||||
break;
|
||||
case GSM48_MT_RR_CLSM_CHG:
|
||||
handle_classmark_chg(conn, msg);
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
/* Normally, a MSC should never receive RR
|
||||
* messages, but we'd rather forward what we
|
||||
* don't know than drop it... */
|
||||
LOGP(DRR, LOGL_NOTICE, "BSC: Passing unknown 04.08 "
|
||||
"RR message type 0x%02x to MSC\n", gh->msg_type);
|
||||
if (api->dtap)
|
||||
api->dtap(conn, link_id, msg);
|
||||
}
|
||||
break;
|
||||
case GSM48_PDISC_MM:
|
||||
default:
|
||||
if (api->dtap)
|
||||
api->dtap(conn, link_id, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
/* default case */
|
||||
if (api->dtap)
|
||||
api->dtap(conn, link_id, msg);
|
||||
}
|
||||
|
||||
/*! \brief RSL has received a DATA INDICATION with L3 from MS */
|
||||
|
|
|
@ -134,7 +134,7 @@ int gsm48_cc_tx_notify_ss(struct gsm_trans *trans, const char *message)
|
|||
return gsm48_conn_sendmsg(ss_notify, trans->conn, trans);
|
||||
}
|
||||
|
||||
static void release_security_operation(struct gsm_subscriber_connection *conn)
|
||||
void release_security_operation(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
if (!conn->sec_operation)
|
||||
return;
|
||||
|
@ -144,7 +144,7 @@ static void release_security_operation(struct gsm_subscriber_connection *conn)
|
|||
msc_release_connection(conn);
|
||||
}
|
||||
|
||||
static void allocate_security_operation(struct gsm_subscriber_connection *conn)
|
||||
void allocate_security_operation(struct gsm_subscriber_connection *conn)
|
||||
{
|
||||
conn->sec_operation = talloc_zero(tall_authciphop_ctx,
|
||||
struct gsm_security_operation);
|
||||
|
@ -1101,29 +1101,6 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int gsm48_rx_rr_status(struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
||||
DEBUGP(DRR, "STATUS rr_cause = %s\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsm48_rx_rr_meas_rep(struct msgb *msg)
|
||||
{
|
||||
struct gsm_meas_rep *meas_rep = lchan_next_meas_rep(msg->lchan);
|
||||
|
||||
/* This shouldn't actually end up here, as RSL treats
|
||||
* L3 Info of 08.58 MEASUREMENT REPORT different by calling
|
||||
* directly into gsm48_parse_meas_rep */
|
||||
DEBUGP(DMEAS, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
|
||||
gsm48_parse_meas_rep(meas_rep, msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
@ -1141,69 +1118,6 @@ static int gsm48_rx_rr_app_info(struct gsm_subscriber_connection *conn, struct m
|
|||
return db_apdu_blob_store(conn->subscr, apdu_id_flags, apdu_len, apdu_data);
|
||||
}
|
||||
|
||||
/* Chapter 9.1.10 Ciphering Mode Complete */
|
||||
static int gsm48_rx_rr_ciph_m_compl(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
gsm_cbfn *cb;
|
||||
int rc = 0;
|
||||
|
||||
DEBUGP(DRR, "CIPHERING MODE COMPLETE\n");
|
||||
|
||||
/* Safety check */
|
||||
if (!conn->sec_operation) {
|
||||
DEBUGP(DRR, "No authentication/cipher operation in progress !!!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* FIXME: check for MI (if any) */
|
||||
|
||||
/* Call back whatever was in progress (if anything) ... */
|
||||
cb = conn->sec_operation->cb;
|
||||
if (cb) {
|
||||
rc = cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_SUCCEEDED,
|
||||
NULL, conn, conn->sec_operation->cb_data);
|
||||
}
|
||||
|
||||
/* Complete the operation */
|
||||
release_security_operation(conn);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Chapter 9.1.16 Handover complete */
|
||||
static int gsm48_rx_rr_ho_compl(struct msgb *msg)
|
||||
{
|
||||
struct lchan_signal_data sig;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
||||
DEBUGP(DRR, "HANDOVER COMPLETE cause = %s\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
|
||||
sig.lchan = msg->lchan;
|
||||
sig.mr = NULL;
|
||||
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_COMPL, &sig);
|
||||
/* FIXME: release old channel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Chapter 9.1.17 Handover Failure */
|
||||
static int gsm48_rx_rr_ho_fail(struct msgb *msg)
|
||||
{
|
||||
struct lchan_signal_data sig;
|
||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||
|
||||
DEBUGP(DRR, "HANDOVER FAILED cause = %s\n",
|
||||
rr_cause_name(gh->data[0]));
|
||||
|
||||
sig.lchan = msg->lchan;
|
||||
sig.mr = NULL;
|
||||
osmo_signal_dispatch(SS_LCHAN, S_LCHAN_HANDOVER_FAIL, &sig);
|
||||
/* FIXME: release allocated new channel */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Receive a GSM 04.08 Radio Resource (RR) message */
|
||||
static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
|
@ -1211,32 +1125,14 @@ static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *m
|
|||
int rc = 0;
|
||||
|
||||
switch (gh->msg_type) {
|
||||
case GSM48_MT_RR_GPRS_SUSP_REQ:
|
||||
DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
|
||||
break;
|
||||
case GSM48_MT_RR_PAG_RESP:
|
||||
rc = gsm48_rx_rr_pag_resp(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_STATUS:
|
||||
rc = gsm48_rx_rr_status(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_MEAS_REP:
|
||||
rc = gsm48_rx_rr_meas_rep(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_APP_INFO:
|
||||
rc = gsm48_rx_rr_app_info(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_CIPH_M_COMPL:
|
||||
rc = gsm48_rx_rr_ciph_m_compl(conn, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_HANDO_COMPL:
|
||||
rc = gsm48_rx_rr_ho_compl(msg);
|
||||
break;
|
||||
case GSM48_MT_RR_HANDO_FAIL:
|
||||
rc = gsm48_rx_rr_ho_fail(msg);
|
||||
break;
|
||||
default:
|
||||
LOGP(DRR, LOGL_NOTICE, "Unimplemented "
|
||||
LOGP(DRR, LOGL_NOTICE, "MSC: Unimplemented "
|
||||
"GSM 04.08 RR msg type 0x%02x\n", gh->msg_type);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -101,6 +101,34 @@ static void msc_classmark_chg(struct gsm_subscriber_connection *conn,
|
|||
}
|
||||
}
|
||||
|
||||
static void msc_ciph_m_compl(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint8_t alg_id)
|
||||
{
|
||||
gsm_cbfn *cb;
|
||||
|
||||
DEBUGP(DRR, "CIPHERING MODE COMPLETE\n");
|
||||
|
||||
/* Safety check */
|
||||
if (!conn->sec_operation) {
|
||||
DEBUGP(DRR, "No authentication/cipher operation in progress !!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: check for MI (if any) */
|
||||
|
||||
/* Call back whatever was in progress (if anything) ... */
|
||||
cb = conn->sec_operation->cb;
|
||||
if (cb) {
|
||||
int rc;
|
||||
rc = cb(GSM_HOOK_RR_SECURITY, GSM_SECURITY_SUCCEEDED,
|
||||
NULL, conn, conn->sec_operation->cb_data);
|
||||
|
||||
}
|
||||
|
||||
/* Complete the operation */
|
||||
release_security_operation(conn);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static struct bsc_api msc_handler = {
|
||||
|
@ -111,6 +139,7 @@ static struct bsc_api msc_handler = {
|
|||
.assign_compl = msc_assign_compl,
|
||||
.assign_fail = msc_assign_fail,
|
||||
.classmark_chg = msc_classmark_chg,
|
||||
.cipher_mode_compl = msc_ciph_m_compl,
|
||||
};
|
||||
|
||||
struct bsc_api *msc_bsc_api() {
|
||||
|
|
Loading…
Reference in New Issue