aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/gsm_04_08.h5
-rw-r--r--openbsc/include/openbsc/gsm_data.h2
-rw-r--r--openbsc/src/abis_rsl.c4
-rw-r--r--openbsc/src/bs11_config.c5
-rw-r--r--openbsc/src/gsm_04_08_utils.c31
-rw-r--r--openbsc/src/gsm_data.c2
-rw-r--r--openbsc/src/vty_interface.c1
-rw-r--r--openbsc/tests/channel/channel_test.c1
8 files changed, 43 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h
index c4018cd11..602658331 100644
--- a/openbsc/include/openbsc/gsm_04_08.h
+++ b/openbsc/include/openbsc/gsm_04_08.h
@@ -16,8 +16,9 @@ struct gsm_trans;
void gsm0408_allow_everyone(int allow);
int gsm0408_rcvmsg(struct msgb *msg, u_int8_t link_id);
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
-enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci);
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, u_int8_t ra);
+enum gsm_chreq_reason_t get_reason_by_chreq(u_int8_t ra, int neci);
+void gsm_net_update_ctype(struct gsm_network *net);
int gsm48_tx_mm_info(struct gsm_lchan *lchan);
int gsm48_tx_mm_auth_req(struct gsm_lchan *lchan, u_int8_t *rand, int key_seq);
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 5b70d1db6..c8fee474b 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -624,6 +624,8 @@ struct gsm_network {
enum rrlp_mode mode;
} rrlp;
+ enum gsm_chan_t ctype_by_chreq[16];
+
/* a hack for On Waves. It must be signed */
int32_t core_country_code;
int32_t core_network_code;
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 446e081ca..b0f4b6e1a 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -1104,8 +1104,8 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
/* determine channel type (SDCCH/TCH_F/TCH_H) based on
* request reference RA */
- lctype = get_ctype_by_chreq(bts, rqd_ref->ra, bts->network->neci);
- chreq_reason = get_reason_by_chreq(bts, rqd_ref->ra, bts->network->neci);
+ lctype = get_ctype_by_chreq(bts->network, rqd_ref->ra);
+ chreq_reason = get_reason_by_chreq(rqd_ref->ra, bts->network->neci);
counter_inc(bts->network->stats.chreq.total);
diff --git a/openbsc/src/bs11_config.c b/openbsc/src/bs11_config.c
index 80f9ba956..de426aa9c 100644
--- a/openbsc/src/bs11_config.c
+++ b/openbsc/src/bs11_config.c
@@ -870,3 +870,8 @@ int main(int argc, char **argv)
exit(0);
}
+
+/* dummy to be able to compile */
+void gsm_net_update_ctype(struct gsm_network *net)
+{
+}
diff --git a/openbsc/src/gsm_04_08_utils.c b/openbsc/src/gsm_04_08_utils.c
index 68f34f409..ad1040b3b 100644
--- a/openbsc/src/gsm_04_08_utils.c
+++ b/openbsc/src/gsm_04_08_utils.c
@@ -164,13 +164,36 @@ static const enum gsm_chreq_reason_t reason_by_chreq[] = {
[CHREQ_T_RESERVED_IGNORE] = GSM_CHREQ_REASON_OTHER,
};
-enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
+/* verify that the two tables match */
+static_assert(sizeof(ctype_by_chreq) ==
+ sizeof(((struct gsm_network *) NULL)->ctype_by_chreq), assert_size);
+
+/*
+ * Update channel types for request based on policy. E.g. in the
+ * case of a TCH/H network/bsc use TCH/H for the emergency calls,
+ * for early assignment assign a SDCCH and some other options.
+ */
+void gsm_net_update_ctype(struct gsm_network *network)
+{
+ /* copy over the data */
+ memcpy(network->ctype_by_chreq, ctype_by_chreq, sizeof(ctype_by_chreq));
+
+ /*
+ * Use TCH/H for emergency calls when this cell allows TCH/H. Maybe it
+ * is better to iterate over the BTS/TRX and check if no TCH/F is available
+ * and then set it to TCH/H.
+ */
+ if (network->neci)
+ network->ctype_by_chreq[CHREQ_T_EMERG_CALL] = GSM_LCHAN_TCH_H;
+}
+
+enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *network, u_int8_t ra)
{
int i;
int length;
const struct chreq *chreq;
- if (neci) {
+ if (network->neci) {
chreq = chreq_type_neci1;
length = ARRAY_SIZE(chreq_type_neci1);
} else {
@@ -182,13 +205,13 @@ enum gsm_chan_t get_ctype_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
for (i = 0; i < length; i++) {
const struct chreq *chr = &chreq[i];
if ((ra & chr->mask) == chr->val)
- return ctype_by_chreq[chr->type];
+ return network->ctype_by_chreq[chr->type];
}
LOGP(DRR, LOGL_ERROR, "Unknown CHANNEL REQUEST RQD 0x%02x\n", ra);
return GSM_LCHAN_SDCCH;
}
-enum gsm_chreq_reason_t get_reason_by_chreq(struct gsm_bts *bts, u_int8_t ra, int neci)
+enum gsm_chreq_reason_t get_reason_by_chreq(u_int8_t ra, int neci)
{
int i;
int length;
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index c4d0431a3..5efebc208 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -296,6 +296,8 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->mncc_recv = mncc_recv;
+ gsm_net_update_ctype(net);
+
net->core_country_code = -1;
net->core_network_code = -1;
net->rtp_base_port = 4000;
diff --git a/openbsc/src/vty_interface.c b/openbsc/src/vty_interface.c
index 09b95cac1..a5ed0d21a 100644
--- a/openbsc/src/vty_interface.c
+++ b/openbsc/src/vty_interface.c
@@ -1265,6 +1265,7 @@ DEFUN(cfg_net_neci,
"Set if NECI of cell selection is to be set")
{
gsmnet->neci = atoi(argv[0]);
+ gsm_net_update_ctype(gsmnet);
return CMD_SUCCESS;
}
diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c
index 4c57a75c6..96f13cbbd 100644
--- a/openbsc/tests/channel/channel_test.c
+++ b/openbsc/tests/channel/channel_test.c
@@ -77,6 +77,7 @@ void nm_state_event() {}
void input_event() {}
void sms_alloc() {}
void _lchan_release() {}
+void gsm_net_update_ctype(struct gsm_network *network) {}
struct tlv_definition nm_att_tlvdef;