aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);