Get TRX attributes
Request per-TRX attributes in addition to BTS attributes. Change-Id: I2b61131b9930afd03357c0b66947ee856d58cc46 Related: OS#1614
This commit is contained in:
parent
4a824ca8fc
commit
33e1357a90
|
@ -512,6 +512,7 @@ enum gsm_bts_type_variant {
|
||||||
enum bts_attribute {
|
enum bts_attribute {
|
||||||
BTS_TYPE_VARIANT,
|
BTS_TYPE_VARIANT,
|
||||||
BTS_SUB_MODEL,
|
BTS_SUB_MODEL,
|
||||||
|
TRX_PHY_VERSION,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vty;
|
struct vty;
|
||||||
|
|
|
@ -439,14 +439,14 @@ int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw_descr,
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool handle_attr(struct gsm_bts *bts, enum bts_attribute id, uint8_t *val, uint8_t len)
|
static inline bool handle_attr(const struct gsm_bts *bts, enum bts_attribute id, uint8_t *val, uint8_t len)
|
||||||
{
|
{
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case BTS_TYPE_VARIANT:
|
case BTS_TYPE_VARIANT:
|
||||||
LOGP(DNM, LOGL_ERROR, "BTS reported variant: %s\n", val);
|
LOGP(DNM, LOGL_NOTICE, "BTS%u reported variant: %s\n", bts->nr, val);
|
||||||
break;
|
break;
|
||||||
case BTS_SUB_MODEL:
|
case BTS_SUB_MODEL:
|
||||||
LOGP(DNM, LOGL_ERROR, "BTS reported submodel: %s\n", val);
|
LOGP(DNM, LOGL_NOTICE, "BTS%u reported submodel: %s\n", bts->nr, val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -454,55 +454,87 @@ static inline bool handle_attr(struct gsm_bts *bts, enum bts_attribute id, uint8
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse Attribute Response Info - return pointer to the actual content */
|
||||||
|
static inline uint8_t *parse_attr_resp_info_unreported(uint8_t bts_nr, uint8_t *ari, uint16_t ari_len, uint16_t *out_len)
|
||||||
|
{
|
||||||
|
uint8_t num_unreported = ari[0], i;
|
||||||
|
|
||||||
|
DEBUGP(DNM, "BTS%u Get Attributes Response Info: %u bytes total with %u unreported attributes\n",
|
||||||
|
bts_nr, ari_len, num_unreported);
|
||||||
|
|
||||||
|
/* +1 because we have to account for number of unreported attributes, prefixing the list: */
|
||||||
|
for (i = 0; i < num_unreported; i++)
|
||||||
|
LOGP(DNM, LOGL_ERROR, "BTS%u Attribute %s is unreported\n",
|
||||||
|
bts_nr, get_value_string(abis_nm_att_names, ari[i + 1]));
|
||||||
|
|
||||||
|
/* the data starts right after the list of unreported attributes + space for length of that list */
|
||||||
|
*out_len = ari_len - (num_unreported + 2);
|
||||||
|
|
||||||
|
return ari + num_unreported + 1; /* we have to account for 1st byte with number of unreported attributes */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Attribute Response Info content for 3GPP TS 52.021 §9.4.28 Manufacturer Dependent State */
|
||||||
|
static inline uint8_t *parse_attr_resp_info_manuf_state(const struct gsm_bts_trx *trx, uint8_t *data, uint16_t *data_len)
|
||||||
|
{
|
||||||
|
struct tlv_parsed tp;
|
||||||
|
const uint8_t *power;
|
||||||
|
uint8_t adjust = 0;
|
||||||
|
|
||||||
|
if (!trx) /* this attribute does not make sense on BTS level, only on TRX level */
|
||||||
|
return data;
|
||||||
|
|
||||||
|
abis_nm_tlv_parse(&tp, trx->bts, data, *data_len);
|
||||||
|
if (TLVP_PRES_LEN(&tp, NM_ATT_MANUF_STATE, 1)) {
|
||||||
|
power = TLVP_VAL(&tp, NM_ATT_MANUF_STATE);
|
||||||
|
LOGP(DNM, LOGL_NOTICE, "%s Get Attributes Response: nominal power is %u\n", gsm_trx_name(trx), *power);
|
||||||
|
adjust = 2; /* adjust for parsed TV struct */
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_len -= adjust;
|
||||||
|
|
||||||
|
return data + adjust;
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle 3GPP TS 52.021 §9.4.64 Get Attribute Response Info */
|
/* Handle 3GPP TS 52.021 §9.4.64 Get Attribute Response Info */
|
||||||
static int abis_nm_rx_get_attr_resp(struct msgb *mb, struct gsm_bts *bts)
|
static int abis_nm_rx_get_attr_resp(struct msgb *mb, const struct gsm_bts_trx *trx)
|
||||||
{
|
{
|
||||||
struct abis_om_hdr *oh = msgb_l2(mb);
|
struct abis_om_hdr *oh = msgb_l2(mb);
|
||||||
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
struct abis_om_fom_hdr *foh = msgb_l3(mb);
|
||||||
struct e1inp_sign_link *sign_link = mb->dst;
|
struct e1inp_sign_link *sign_link = mb->dst;
|
||||||
|
struct gsm_bts *bts = trx ? trx->bts : sign_link->trx->bts;
|
||||||
struct tlv_parsed tp;
|
struct tlv_parsed tp;
|
||||||
const uint8_t *ari;
|
uint8_t *data, i;
|
||||||
uint8_t unreported, i;
|
uint16_t data_len;
|
||||||
uint16_t ari_len;
|
|
||||||
int rc;
|
int rc;
|
||||||
struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];
|
struct abis_nm_sw_desc sw_descr[MAX_BTS_ATTR];
|
||||||
|
|
||||||
abis_nm_debugp_foh(DNM, foh);
|
abis_nm_debugp_foh(DNM, foh);
|
||||||
|
|
||||||
DEBUGPC(DNM, "Get Attributes Response\n");
|
DEBUGPC(DNM, "Get Attributes Response for BTS%u\n", bts->nr);
|
||||||
|
|
||||||
abis_nm_tlv_parse(&tp, sign_link->trx->bts, foh->data, oh->length-sizeof(*foh));
|
abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
|
||||||
|
if (!TLVP_PRES_LEN(&tp, NM_ATT_GET_ARI, 1)) {
|
||||||
if (!TLVP_PRESENT(&tp, NM_ATT_GET_ARI)) {
|
LOGP(DNM, LOGL_ERROR, "BTS%u: Get Attributes Response without Response Info?!\n", bts->nr);
|
||||||
LOGP(DNM, LOGL_ERROR, "Get Attributes Response without Response Info?!\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ari = TLVP_VAL(&tp, NM_ATT_GET_ARI);
|
data = parse_attr_resp_info_unreported(bts->nr, TLVP_VAL(&tp, NM_ATT_GET_ARI), TLVP_LEN(&tp, NM_ATT_GET_ARI),
|
||||||
ari_len = TLVP_LEN(&tp, NM_ATT_GET_ARI);
|
&data_len);
|
||||||
/* Attributes Response Info has peculiar structure - first the number of unreported attributes */
|
|
||||||
unreported = ari[0];
|
|
||||||
DEBUGP(DNM, "Found Get Attributes Response Info: %u bytes total with %u unreported attributes\n",
|
|
||||||
ari_len, unreported);
|
|
||||||
|
|
||||||
/* than the list of unreported attributes */
|
data = parse_attr_resp_info_manuf_state(trx, data, &data_len);
|
||||||
for (i = 0; i < unreported; i++)
|
|
||||||
LOGP(DNM, LOGL_ERROR, "Attribute %s is unreported\n", /* +1 because we have to account for number of */
|
|
||||||
get_value_string(abis_nm_att_names, ari[i + 1])); /* unreported attributes, prefixing the list. */
|
|
||||||
|
|
||||||
/* after that there's finally list of replies in form of sw-conf structure:
|
/* after parsing manufacturer-specific attributes there's list of replies in form of sw-conf structure: */
|
||||||
it starts right after the list of unreported attributes + space for length of that list */
|
rc = abis_nm_get_sw_conf(data, data_len, &sw_descr[0], ARRAY_SIZE(sw_descr));
|
||||||
rc = abis_nm_get_sw_conf(ari + unreported + 1, ari_len - (unreported + 2), &sw_descr[0], ARRAY_SIZE(sw_descr));
|
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
for (i = 0; i < rc; i++) {
|
for (i = 0; i < rc; i++) {
|
||||||
if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id), sw_descr[i].file_version,
|
if (!handle_attr(bts, str2btsattr((const char *)sw_descr[i].file_id),
|
||||||
sw_descr[i].file_version_len))
|
sw_descr[i].file_version, sw_descr[i].file_version_len))
|
||||||
LOGP(DNM, LOGL_NOTICE, "ARI reported sw[%d/%d]: %s is %s\n",
|
LOGP(DNM, LOGL_NOTICE, "BTS%u: ARI reported sw[%d/%d]: %s is %s\n",
|
||||||
i, rc, sw_descr[i].file_id, sw_descr[i].file_version);
|
bts->nr, i, rc, sw_descr[i].file_id, sw_descr[i].file_version);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
LOGP(DNM, LOGL_ERROR, "Failed to parse SW-Config part of Get Attribute Response Info: %s\n",
|
LOGP(DNM, LOGL_ERROR, "BTS%u: failed to parse SW-Config part of Get Attribute Response Info: %s\n",
|
||||||
strerror(-rc));
|
bts->nr, strerror(-rc));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -720,7 +752,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
|
||||||
case NM_MT_SET_BTS_ATTR_ACK:
|
case NM_MT_SET_BTS_ATTR_ACK:
|
||||||
break;
|
break;
|
||||||
case NM_MT_GET_ATTR_RESP:
|
case NM_MT_GET_ATTR_RESP:
|
||||||
ret = abis_nm_rx_get_attr_resp(mb, bts);
|
ret = abis_nm_rx_get_attr_resp(mb, gsm_bts_trx_num(bts, (foh)->obj_inst.trx_nr));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abis_nm_debugp_foh(DNM, foh);
|
abis_nm_debugp_foh(DNM, foh);
|
||||||
|
|
|
@ -316,10 +316,13 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal,
|
||||||
struct input_signal_data *isd = signal_data;
|
struct input_signal_data *isd = signal_data;
|
||||||
struct gsm_bts_trx *trx = isd->trx;
|
struct gsm_bts_trx *trx = isd->trx;
|
||||||
int ts_no, lchan_no;
|
int ts_no, lchan_no;
|
||||||
const uint8_t attr[] = { NM_ATT_SW_CONFIG, };
|
/* N. B: we rely on attribute order when parsing response in abis_nm_rx_get_attr_resp() */
|
||||||
|
const uint8_t bts_attr[] = { NM_ATT_MANUF_ID, NM_ATT_SW_CONFIG, };
|
||||||
|
const uint8_t trx_attr[] = { NM_ATT_MANUF_STATE, NM_ATT_SW_CONFIG, };
|
||||||
|
|
||||||
/* we should not request more attributes than we're ready to handle */
|
/* we should not request more attributes than we're ready to handle */
|
||||||
OSMO_ASSERT(sizeof(attr) < MAX_BTS_ATTR);
|
OSMO_ASSERT(sizeof(bts_attr) < MAX_BTS_ATTR);
|
||||||
|
OSMO_ASSERT(sizeof(trx_attr) < MAX_BTS_ATTR);
|
||||||
|
|
||||||
if (subsys != SS_L_INPUT)
|
if (subsys != SS_L_INPUT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -339,14 +342,17 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal,
|
||||||
set bts->si_common.cell_alloc */
|
set bts->si_common.cell_alloc */
|
||||||
generate_cell_chan_list(ca, trx->bts);
|
generate_cell_chan_list(ca, trx->bts);
|
||||||
|
|
||||||
|
/* Request generic BTS-level attributes */
|
||||||
|
abis_nm_get_attr(trx->bts, NM_OC_BTS, trx->bts->nr, trx->nr, 0xFF, bts_attr, sizeof(bts_attr));
|
||||||
|
|
||||||
llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
|
llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) {
|
||||||
int i;
|
int i;
|
||||||
|
/* Request TRX-level attributes */
|
||||||
|
abis_nm_get_attr(cur_trx->bts, NM_OC_BASEB_TRANSC, cur_trx->bts->nr, cur_trx->nr, 0xFF,
|
||||||
|
trx_attr, sizeof(trx_attr));
|
||||||
for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
|
for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++)
|
||||||
generate_ma_for_ts(&cur_trx->ts[i]);
|
generate_ma_for_ts(&cur_trx->ts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
abis_nm_get_attr(trx->bts, NM_OC_BTS, trx->bts->nr, trx->nr, 0xFF, attr, sizeof(attr));
|
|
||||||
}
|
}
|
||||||
if (isd->link_type == E1INP_SIGN_RSL)
|
if (isd->link_type == E1INP_SIGN_RSL)
|
||||||
bootstrap_rsl(trx);
|
bootstrap_rsl(trx);
|
||||||
|
|
|
@ -54,6 +54,7 @@ static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts,
|
||||||
const struct value_string bts_attribute_names[] = {
|
const struct value_string bts_attribute_names[] = {
|
||||||
OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
|
OSMO_VALUE_STRING(BTS_TYPE_VARIANT),
|
||||||
OSMO_VALUE_STRING(BTS_SUB_MODEL),
|
OSMO_VALUE_STRING(BTS_SUB_MODEL),
|
||||||
|
OSMO_VALUE_STRING(TRX_PHY_VERSION),
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue