From cf149eebb69ac015dc0f4a3eed57821c862300de Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 23 Jan 2012 16:40:24 +0100 Subject: 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. --- openbsc/include/openbsc/gsm_04_08.h | 3 + openbsc/src/libbsc/bsc_api.c | 83 +++++++++++++++++++++++---- openbsc/src/libmsc/gsm_04_08.c | 110 +----------------------------------- openbsc/src/libmsc/osmo_msc.c | 29 ++++++++++ 4 files changed, 107 insertions(+), 118 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index ec6c2c001..2f5aaa98c 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -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 diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index bb1374776..9d301f002 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -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 */ diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index a2a49aa9a..20a2cc502 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -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; } diff --git a/openbsc/src/libmsc/osmo_msc.c b/openbsc/src/libmsc/osmo_msc.c index 121de679c..4c0862aae 100644 --- a/openbsc/src/libmsc/osmo_msc.c +++ b/openbsc/src/libmsc/osmo_msc.c @@ -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() { -- cgit v1.2.3