aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylvain Munaut <tnt@246tNt.com>2020-05-05 21:07:58 +0200
committerSylvain Munaut <tnt@246tNt.com>2020-05-08 15:16:15 +0200
commitdbd1b50604a36b6a5adb01d36796e19c1320a0c3 (patch)
tree9d37478cb2707ff75452e488c4c4bc0cd21dae79
parentce0b5627856a4d6e7b2e3731d5cc1fe1f0cd269a (diff)
om2k: Add option to limit OML version during negotiation
Starting from G12R13 the MCTR swiches to BSC controlled mode. And although we think we know how to configure it (via MCTR Conf Req), something doesn't work right and the timeslot configuration is not accepted. (TS Conf Result shows "Data not according to request"). So as a workaround for now, we use this version of the protocol where we don't configure the MCTR (it's in "BTS controlled mode") and with this protocol, the BTS accepts our timeslot config and we can bring the system up. This commit add a generic option to limit either OML or RSL IWD version to any value. It also keeps track of the actual negotation version so we can react to it in other places of the code. Signed-off-by: Sylvain Munaut <tnt@246tNt.com> Change-Id: I8f0b0ba72056ea4250fe490e7a38630c77c04f65 better version limit Change-Id: Ia789f8ede3eab7eeca6c759da0109e0b53398f60
-rw-r--r--include/osmocom/bsc/gsm_data.h4
-rw-r--r--src/osmo-bsc/abis_om2000.c52
-rw-r--r--src/osmo-bsc/abis_om2000_vty.c43
3 files changed, 91 insertions, 8 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 1d02e3943..c2115a628 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -1135,6 +1135,10 @@ struct gsm_bts {
struct gsm_abis_mo mo;
} tf;
uint32_t use_superchannel:1;
+ struct {
+ uint16_t limit;
+ uint16_t active;
+ } om2k_version[16];
} rbs2000;
struct {
uint8_t bts_type;
diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c
index e20d9a65e..f5d8095fc 100644
--- a/src/osmo-bsc/abis_om2000.c
+++ b/src/osmo-bsc/abis_om2000.c
@@ -2447,8 +2447,8 @@ static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2
}
struct iwd_version {
- uint8_t gen_char[3+1];
- uint8_t rev_char[3+1];
+ char gen_char[3+1];
+ char rev_char[3+1];
};
struct iwd_type {
@@ -2459,11 +2459,13 @@ struct iwd_type {
static int om2k_rx_negot_req(struct msgb *msg)
{
struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst;
+ struct gsm_bts *bts = sign_link->trx->bts;
struct abis_om2k_hdr *o2h = msgb_l2(msg);
struct iwd_type iwd_types[16];
uint8_t num_iwd_types = o2h->data[2];
uint8_t *cur = o2h->data+3;
- unsigned int i, v;
+ unsigned int i;
+ int v;
uint8_t out_buf[1024];
uint8_t *out_cur = out_buf+1;
@@ -2494,25 +2496,59 @@ static int om2k_rx_negot_req(struct msgb *msg)
/* Select the last version for each IWD type */
for (i = 0; i < ARRAY_SIZE(iwd_types); i++) {
struct iwd_type *type = &iwd_types[i];
- struct iwd_version *last_v;
+ struct iwd_version *sel_v = NULL, *alt_v = NULL;
+ uint16_t sel_ver, alt_ver = 0;
+ int gen, rev;
if (type->num_vers == 0)
continue;
out_num_types++;
- last_v = &type->v[type->num_vers-1];
+ for (v = type->num_vers-1; v >= 0; v--) {
+ if ((sscanf(type->v[v].gen_char, "G%2d", &gen) != 1) ||
+ (sscanf(type->v[v].rev_char, "R%2d", &rev) != 1))
+ continue;
+ sel_ver = (gen << 8) | rev;
+
+ if (!alt_v) {
+ alt_ver = sel_ver;
+ alt_v = &type->v[v];
+ }
+
+ if ((bts->rbs2000.om2k_version[i].limit != 0) &&
+ (bts->rbs2000.om2k_version[i].limit < sel_ver))
+ continue;
+
+ sel_v = &type->v[v];
+ break;
+ }
+ if (!sel_v) {
+ if (!alt_v) {
+ LOGP(DNM, LOGL_ERROR, "Couldn't find valid version for IWD Type %u."
+ "Skipping IWD ... this will most likely fail\n", i);
+ continue;
+ } else {
+ sel_v = alt_v;
+ sel_ver = alt_ver;
+ LOGP(DNM, LOGL_ERROR, "Couldn't find suitable version for IWD Type %u."
+ "Fallback to Gen %s Rev %s\n", i,
+ sel_v->gen_char, sel_v->rev_char);
+ }
+ }
+
+ bts->rbs2000.om2k_version[i].active = sel_ver;
*out_cur++ = i;
- memcpy(out_cur, last_v->gen_char, 3);
+ memcpy(out_cur, sel_v->gen_char, 3);
out_cur += 3;
- memcpy(out_cur, last_v->rev_char, 3);
+ memcpy(out_cur, sel_v->rev_char, 3);
out_cur += 3;
}
out_buf[0] = out_num_types;
- return abis_om2k_tx_negot_req_ack(sign_link->trx->bts, &o2h->mo, out_buf, out_cur - out_buf);
+ return abis_om2k_tx_negot_req_ack(bts, &o2h->mo, out_buf, out_cur - out_buf);
}
diff --git a/src/osmo-bsc/abis_om2000_vty.c b/src/osmo-bsc/abis_om2000_vty.c
index 972fff04a..222546f87 100644
--- a/src/osmo-bsc/abis_om2000_vty.c
+++ b/src/osmo-bsc/abis_om2000_vty.c
@@ -467,6 +467,40 @@ DEFUN(cfg_bts_alt_mode, cfg_bts_alt_mode_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_bts_om2k_version_limit, cfg_bts_om2k_version_limit_cmd,
+ "om2000 version-limit (oml|rsl) gen <0-99> rev <0-99>",
+ "Configure OM2K specific parameters\n"
+ "Configure optional maximum protocol version to negotiate\n"
+ "Limit OML IWD version\n" "Limit RSL IWD version\n"
+ "Generation limit\n"
+ "Generation number to limit to (inclusive)\n"
+ "Revision limit\n"
+ "Revision number to limit to (inclusive)\n")
+{
+ struct gsm_bts *bts = vty->index;
+ int iwd;
+
+ if (bts->type != GSM_BTS_TYPE_RBS2000) {
+ vty_out(vty, "%% Command only works for RBS2000%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(argv[0], "oml"))
+ iwd = 0;
+ else if (!strcmp(argv[0], "rsl"))
+ iwd = 1;
+ else {
+ vty_out(vty, "%% Invalid IWD%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts->rbs2000.om2k_version[iwd].limit = (atoi(argv[1]) << 8) | atoi(argv[2]);
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd,
"is-connection-list (add|del) <0-2047> <0-2047> <0-255>",
"Interface Switch Connection List\n"
@@ -591,6 +625,7 @@ void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
{
struct is_conn_group *igrp;
struct con_group *cgrp;
+ unsigned int i;
llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list)
vty_out(vty, " is-connection-list add %u %u %u%s",
@@ -604,6 +639,13 @@ void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts)
if (bts->rbs2000.use_superchannel)
vty_out(vty, " abis-lower-transport super-channel%s",
VTY_NEWLINE);
+ for (i = 0; i < 2; i++)
+ if (bts->rbs2000.om2k_version[i].limit)
+ vty_out(vty, " om2000 version-limit %s gen %02d rev %02d%s",
+ i ? "rsl" : "oml",
+ (bts->rbs2000.om2k_version[i].limit >> 8),
+ (bts->rbs2000.om2k_version[i].limit & 0xff),
+ VTY_NEWLINE);
}
int abis_om2k_vty_init(void)
@@ -631,6 +673,7 @@ int abis_om2k_vty_init(void)
install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd);
install_element(BTS_NODE, &cfg_bts_alt_mode_cmd);
+ install_element(BTS_NODE, &cfg_bts_om2k_version_limit_cmd);
install_element(BTS_NODE, &cfg_om2k_con_group_cmd);
install_element(BTS_NODE, &del_om2k_con_group_cmd);