Move processing of CLASSMARK CHANGE behind bsc_api
This prevents osmo-bsc from sending RR messages to the MSC and rather process them inside the BSC and turn them into BSSAP CM UPDATE.
This commit is contained in:
parent
d55cef9b07
commit
95e862cab4
|
@ -30,6 +30,10 @@ struct bsc_api {
|
||||||
/*! \brief BSC->MSC: RR conn has been cleared */
|
/*! \brief BSC->MSC: RR conn has been cleared */
|
||||||
int (*clear_request)(struct gsm_subscriber_connection *conn,
|
int (*clear_request)(struct gsm_subscriber_connection *conn,
|
||||||
uint32_t cause);
|
uint32_t cause);
|
||||||
|
/*! \brief BSC->MSC: Classmark Update */
|
||||||
|
void (*classmark_chg)(struct gsm_subscriber_connection *conn,
|
||||||
|
const uint8_t *cm2, uint8_t cm2_len,
|
||||||
|
const uint8_t *cm3, uint8_t cm3_len);
|
||||||
};
|
};
|
||||||
|
|
||||||
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
|
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
|
||||||
|
|
|
@ -418,6 +418,44 @@ static void handle_ass_fail(struct gsm_subscriber_connection *conn,
|
||||||
rr_failure);
|
rr_failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_classmark_chg(struct gsm_subscriber_connection *conn,
|
||||||
|
struct msgb *msg)
|
||||||
|
{
|
||||||
|
struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
|
||||||
|
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||||
|
unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
|
||||||
|
uint8_t cm2_len, cm3_len = 0;
|
||||||
|
uint8_t *cm2, *cm3 = NULL;
|
||||||
|
|
||||||
|
DEBUGP(DRR, "CLASSMARK CHANGE ");
|
||||||
|
|
||||||
|
/* classmark 2 */
|
||||||
|
cm2_len = gh->data[0];
|
||||||
|
cm2 = &gh->data[1];
|
||||||
|
DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
|
||||||
|
|
||||||
|
if (payload_len > cm2_len + 1) {
|
||||||
|
/* we must have a classmark3 */
|
||||||
|
if (gh->data[cm2_len+1] != 0x20) {
|
||||||
|
DEBUGPC(DRR, "ERR CM3 TAG\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (cm2_len > 3) {
|
||||||
|
DEBUGPC(DRR, "CM2 too long!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
|
||||||
|
}
|
||||||
|
api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
|
||||||
|
}
|
||||||
|
|
||||||
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
||||||
uint8_t link_id, struct msgb *msg)
|
uint8_t link_id, struct msgb *msg)
|
||||||
{
|
{
|
||||||
|
@ -462,6 +500,10 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
case GSM48_MT_RR_CLSM_CHG:
|
||||||
|
handle_classmark_chg(conn, msg);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GSM48_PDISC_MM:
|
case GSM48_PDISC_MM:
|
||||||
|
|
|
@ -1101,53 +1101,6 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gsm48_rx_rr_classmark(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
|
||||||
{
|
|
||||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
|
||||||
struct gsm_subscriber *subscr = conn->subscr;
|
|
||||||
unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
|
|
||||||
uint8_t cm2_len, cm3_len = 0;
|
|
||||||
uint8_t *cm2, *cm3 = NULL;
|
|
||||||
|
|
||||||
DEBUGP(DRR, "CLASSMARK CHANGE ");
|
|
||||||
|
|
||||||
/* classmark 2 */
|
|
||||||
cm2_len = gh->data[0];
|
|
||||||
cm2 = &gh->data[1];
|
|
||||||
DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);
|
|
||||||
|
|
||||||
if (payload_len > cm2_len + 1) {
|
|
||||||
/* we must have a classmark3 */
|
|
||||||
if (gh->data[cm2_len+1] != 0x20) {
|
|
||||||
DEBUGPC(DRR, "ERR CM3 TAG\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (cm2_len > 3) {
|
|
||||||
DEBUGPC(DRR, "CM2 too long!\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
|
|
||||||
}
|
|
||||||
if (subscr) {
|
|
||||||
subscr->equipment.classmark2_len = cm2_len;
|
|
||||||
memcpy(subscr->equipment.classmark2, cm2, cm2_len);
|
|
||||||
if (cm3) {
|
|
||||||
subscr->equipment.classmark3_len = cm3_len;
|
|
||||||
memcpy(subscr->equipment.classmark3, cm3, cm3_len);
|
|
||||||
}
|
|
||||||
db_sync_equipment(&subscr->equipment);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gsm48_rx_rr_status(struct msgb *msg)
|
static int gsm48_rx_rr_status(struct msgb *msg)
|
||||||
{
|
{
|
||||||
struct gsm48_hdr *gh = msgb_l3(msg);
|
struct gsm48_hdr *gh = msgb_l3(msg);
|
||||||
|
@ -1258,9 +1211,6 @@ static int gsm0408_rcv_rr(struct gsm_subscriber_connection *conn, struct msgb *m
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
switch (gh->msg_type) {
|
switch (gh->msg_type) {
|
||||||
case GSM48_MT_RR_CLSM_CHG:
|
|
||||||
rc = gsm48_rx_rr_classmark(conn, msg);
|
|
||||||
break;
|
|
||||||
case GSM48_MT_RR_GPRS_SUSP_REQ:
|
case GSM48_MT_RR_GPRS_SUSP_REQ:
|
||||||
DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
|
DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <openbsc/bsc_api.h>
|
#include <openbsc/bsc_api.h>
|
||||||
#include <openbsc/debug.h>
|
#include <openbsc/debug.h>
|
||||||
#include <openbsc/transaction.h>
|
#include <openbsc/transaction.h>
|
||||||
|
#include <openbsc/db.h>
|
||||||
|
|
||||||
#include <openbsc/gsm_04_11.h>
|
#include <openbsc/gsm_04_11.h>
|
||||||
|
|
||||||
|
@ -83,6 +84,25 @@ static void msc_assign_fail(struct gsm_subscriber_connection *conn,
|
||||||
"Assignment fail should not have been reached.\n");
|
"Assignment fail should not have been reached.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void msc_classmark_chg(struct gsm_subscriber_connection *conn,
|
||||||
|
const uint8_t *cm2, uint8_t cm2_len,
|
||||||
|
const uint8_t *cm3, uint8_t cm3_len)
|
||||||
|
{
|
||||||
|
struct gsm_subscriber *subscr = conn->subscr;
|
||||||
|
|
||||||
|
if (subscr) {
|
||||||
|
subscr->equipment.classmark2_len = cm2_len;
|
||||||
|
memcpy(subscr->equipment.classmark2, cm2, cm2_len);
|
||||||
|
if (cm3) {
|
||||||
|
subscr->equipment.classmark3_len = cm3_len;
|
||||||
|
memcpy(subscr->equipment.classmark3, cm3, cm3_len);
|
||||||
|
}
|
||||||
|
db_sync_equipment(&subscr->equipment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static struct bsc_api msc_handler = {
|
static struct bsc_api msc_handler = {
|
||||||
.sapi_n_reject = msc_sapi_n_reject,
|
.sapi_n_reject = msc_sapi_n_reject,
|
||||||
.compl_l3 = msc_compl_l3,
|
.compl_l3 = msc_compl_l3,
|
||||||
|
@ -90,6 +110,7 @@ static struct bsc_api msc_handler = {
|
||||||
.clear_request = msc_clear_request,
|
.clear_request = msc_clear_request,
|
||||||
.assign_compl = msc_assign_compl,
|
.assign_compl = msc_assign_compl,
|
||||||
.assign_fail = msc_assign_fail,
|
.assign_fail = msc_assign_fail,
|
||||||
|
.classmark_chg = msc_classmark_chg,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bsc_api *msc_bsc_api() {
|
struct bsc_api *msc_bsc_api() {
|
||||||
|
|
|
@ -183,6 +183,19 @@ static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bsc_cm_update(struct gsm_subscriber_connection *conn,
|
||||||
|
const uint8_t *cm2, uint8_t cm2_len,
|
||||||
|
const uint8_t *cm3, uint8_t cm3_len)
|
||||||
|
{
|
||||||
|
struct osmo_bsc_sccp_con *sccp;
|
||||||
|
struct msgb *resp;
|
||||||
|
return_when_not_connected_val(conn, 1);
|
||||||
|
|
||||||
|
resp = gsm0808_create_classmark_update(cm2, cm2_len, cm3, cm3_len);
|
||||||
|
|
||||||
|
queue_msg_or_return(resp);
|
||||||
|
}
|
||||||
|
|
||||||
static struct bsc_api bsc_handler = {
|
static struct bsc_api bsc_handler = {
|
||||||
.sapi_n_reject = bsc_sapi_n_reject,
|
.sapi_n_reject = bsc_sapi_n_reject,
|
||||||
.cipher_mode_compl = bsc_cipher_mode_compl,
|
.cipher_mode_compl = bsc_cipher_mode_compl,
|
||||||
|
@ -191,6 +204,7 @@ static struct bsc_api bsc_handler = {
|
||||||
.assign_compl = bsc_assign_compl,
|
.assign_compl = bsc_assign_compl,
|
||||||
.assign_fail = bsc_assign_fail,
|
.assign_fail = bsc_assign_fail,
|
||||||
.clear_request = bsc_clear_request,
|
.clear_request = bsc_clear_request,
|
||||||
|
.classmark_chg = bsc_cm_update,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bsc_api *osmo_bsc_api()
|
struct bsc_api *osmo_bsc_api()
|
||||||
|
|
Loading…
Reference in New Issue