diff options
-rw-r--r-- | include/osmocom/bsc/gsm_data.h | 4 | ||||
-rw-r--r-- | src/osmo-bsc/abis_om2000.c | 52 | ||||
-rw-r--r-- | src/osmo-bsc/abis_om2000_vty.c | 43 |
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); |