aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmo-bts/bts.h3
-rw-r--r--include/osmo-bts/gsm_data.h8
-rw-r--r--src/common/bts.c30
-rw-r--r--src/common/rsl.c6
-rw-r--r--src/osmo-bts-octphy/l1_if.c9
-rw-r--r--src/osmo-bts-sysmo/main.c12
-rw-r--r--src/osmo-bts-trx/main.c12
-rw-r--r--tests/misc/misc_test.c26
8 files changed, 106 insertions, 0 deletions
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 9e16e050..2f63e37f 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -45,5 +45,8 @@ struct gsm_time *get_time(struct gsm_bts *bts);
int bts_main(int argc, char **argv);
+int bts_supports_cm(struct gsm_bts_role_bts *bts,
+ enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm);
+
#endif /* _BTS_H */
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index dcffcf65..853b4454 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -33,6 +33,11 @@ struct gsm_network {
struct pcu_sock_state *pcu_state;
};
+struct bts_cm {
+ enum gsm_phys_chan_config pchan;
+ enum gsm48_chan_mode cm;
+};
+
/* data structure for BTS related data specific to the BTS role */
struct gsm_bts_role_bts {
struct {
@@ -89,6 +94,7 @@ struct gsm_bts_role_bts {
bool rtp_jitter_adaptive;
struct {
uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */
+ const struct bts_cm *cm; /* Table with supp. ch rate/mode combinations */
} support;
struct {
uint8_t tc4_ctr;
@@ -146,4 +152,6 @@ int bts_supports_cipher(struct gsm_bts_role_bts *bts, int rsl_cipher);
bool ts_is_pdch(const struct gsm_bts_trx_ts *ts);
+int bts_model_check_cm_mode(enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm);
+
#endif /* _GSM_DATA_H */
diff --git a/src/common/bts.c b/src/common/bts.c
index 6747f50b..31afba41 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -675,3 +675,33 @@ struct gsm_time *get_time(struct gsm_bts *bts)
return &btsb->gsm_time;
}
+
+int bts_supports_cm(struct gsm_bts_role_bts *bts,
+ enum gsm_phys_chan_config pchan, enum gsm48_chan_mode cm)
+{
+ const struct bts_cm *supported;
+ int i;
+
+ supported = bts->support.cm;
+
+ /* Check if we got a list with supported codec, if not, no list has
+ * been configured yet for that BTS. In that case we will just skip
+ * and accept any combination */
+ if (supported == NULL)
+ return 1;
+
+ for (i = 0;; i++) {
+ /* If we manage to find the given combination in the list,
+ * we know that the pchan/cm combination is supported */
+ if (supported[i].pchan == pchan && supported[i].cm == cm)
+ return 1;
+
+ /* When we hit the terminator, we know that the given
+ * pchan/cm combination is not supported because it
+ * is not in the list. */
+ if (supported[i].pchan == _GSM_PCHAN_MAX)
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 3d0993c3..2eb0db1d 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -1278,6 +1278,7 @@ static int rsl_rx_mode_modif(struct msgb *msg)
struct gsm_lchan *lchan = msg->lchan;
struct rsl_ie_chan_mode *cm;
struct tlv_parsed tp;
+ struct gsm_bts_role_bts *btsb = bts_role_bts(lchan->ts->trx->bts);
rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg));
@@ -1289,6 +1290,11 @@ static int rsl_rx_mode_modif(struct msgb *msg)
cm = (struct rsl_ie_chan_mode *) TLVP_VAL(&tp, RSL_IE_CHAN_MODE);
lchan_tchmode_from_cmode(lchan, cm);
+ if (bts_supports_cm(btsb, lchan->ts->pchan, lchan->tch_mode) != 1) {
+ LOGP(DRSL, LOGL_ERROR, "invalid mode/codec instructed by BSC, check BSC configuration.\n");
+ return rsl_tx_mode_modif_nack(lchan, RSL_ERR_SERV_OPT_UNAVAIL);
+ }
+
/* 9.3.7 Encryption Information */
if (TLVP_PRESENT(&tp, RSL_IE_ENCR_INFO)) {
uint8_t len = TLVP_LEN(&tp, RSL_IE_ENCR_INFO);
diff --git a/src/osmo-bts-octphy/l1_if.c b/src/osmo-bts-octphy/l1_if.c
index fce34841..dde993d5 100644
--- a/src/osmo-bts-octphy/l1_if.c
+++ b/src/osmo-bts-octphy/l1_if.c
@@ -76,6 +76,14 @@
/* timeout until which we expect PHY to respond */
#define CMD_TIMEOUT 5
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+ { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+ { _GSM_PCHAN_MAX, 0 }
+};
+
/* allocate a msgb for a Layer1 primitive */
struct msgb *l1p_msgb_alloc(void)
{
@@ -776,6 +784,7 @@ int bts_model_init(struct gsm_bts *bts)
bts->variant = BTS_OSMO_OCTPHY;
btsb = bts_role_bts(bts);
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
+ btsb->support.cm = bts_model_supported_cm;
/* FIXME: what is the nominal transmit power of the PHY/board? */
bts->c0->nominal_power = 15;
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index ce12d63d..f52ecdd5 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -55,6 +55,17 @@
#include "hw_misc.h"
#include "oml_router.h"
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+ { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR},
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+ { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+ { _GSM_PCHAN_MAX, 0 }
+};
+
int bts_model_init(struct gsm_bts *bts)
{
struct gsm_bts_role_bts *btsb;
@@ -65,6 +76,7 @@ int bts_model_init(struct gsm_bts *bts)
bts->variant = BTS_OSMO_SYSMO;
btsb = bts_role_bts(bts);
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2) | CIPHER_A5(3);
+ btsb->support.cm = bts_model_supported_cm;
rc = oml_router_init(bts, OML_ROUTER_PATH, &accept_fd, &read_fd);
if (rc < 0) {
diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c
index a1eb686d..973a611e 100644
--- a/src/osmo-bts-trx/main.c
+++ b/src/osmo-bts-trx/main.c
@@ -59,6 +59,17 @@
#include "l1_if.h"
#include "trx_if.h"
+/* Table with channel rate / and codec configuration that are supported
+ * by the hardware bts_supports_cm() */
+static const struct bts_cm bts_model_supported_cm[] = {
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+ { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR},
+ { GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+ { GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+ { _GSM_PCHAN_MAX, 0 }
+};
+
/* dummy, since no direct dsp support */
uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
{
@@ -101,6 +112,7 @@ int bts_model_init(struct gsm_bts *bts)
bts->variant = BTS_OSMO_TRX;
btsb->support.ciphers = CIPHER_A5(1) | CIPHER_A5(2);
+ btsb->support.cm = bts_model_supported_cm;
/* FIXME: this needs to be overridden with the real hardrware
* value */
diff --git a/tests/misc/misc_test.c b/tests/misc/misc_test.c
index c2918fb4..00744a6b 100644
--- a/tests/misc/misc_test.c
+++ b/tests/misc/misc_test.c
@@ -157,6 +157,31 @@ static void test_sacch_get(void)
}
}
+static const struct bts_cm bts_model_supported_cm[] = {
+ {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1},
+ {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1},
+ {GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR},
+ {GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR},
+ {_GSM_PCHAN_MAX, 0}
+};
+
+static void test_bts_supports_cm(void)
+{
+ struct gsm_bts_role_bts bts;
+ bts.support.cm = bts_model_supported_cm;
+
+ OSMO_ASSERT(bts_supports_cm
+ (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_V1) == 1);
+ OSMO_ASSERT(bts_supports_cm
+ (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_V1) == 1);
+ OSMO_ASSERT(bts_supports_cm
+ (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_EFR) == 0);
+ OSMO_ASSERT(bts_supports_cm
+ (&bts, GSM_PCHAN_TCH_F, GSM48_CMODE_SPEECH_AMR) == 1);
+ OSMO_ASSERT(bts_supports_cm
+ (&bts, GSM_PCHAN_TCH_H, GSM48_CMODE_SPEECH_AMR) == 1);
+}
+
int main(int argc, char **argv)
{
bts_log_init(NULL);
@@ -164,5 +189,6 @@ int main(int argc, char **argv)
test_sacch_get();
test_msg_utils_ipa();
test_msg_utils_oml();
+ test_bts_supports_cm();
return EXIT_SUCCESS;
}