diff options
author | Harald Welte <laforge@gnumonks.org> | 2009-08-08 00:02:36 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2009-08-08 00:02:36 +0200 |
commit | c7310385caa5b50fbe81d3e8dc854cd7b4f1014f (patch) | |
tree | 860d6850bb55ca10224ef417803aedee27958d52 /openbsc | |
parent | bd30506628019b228467170c6aac170aba769325 (diff) |
implement nanoBTS frequency error test
This helps us to detect the frequency error of BS-11 if it is located
next to the nanoBTS 900.
If 'ipaccess-config -l' is called, it will produce a report like
<0020> ipaccess-config.c:85 TEST REPORT: test_no=0x42 test_res=0
<0020> ipaccess-config.c:108 ==> ARFCN 220, Frequency Error 22
<0020> ipaccess-config.c:108 ==> ARFCN 1, Frequency Error -37
<0020> ipaccess-config.c:108 ==> ARFCN 10, Frequency Error 0
<0020> ipaccess-config.c:108 ==> ARFCN 20, Frequency Error 11
<0020> ipaccess-config.c:108 ==> ARFCN 53, Frequency Error 5
<0020> ipaccess-config.c:108 ==> ARFCN 63, Frequency Error -4
<0020> ipaccess-config.c:108 ==> ARFCN 84, Frequency Error 11
<0020> ipaccess-config.c:108 ==> ARFCN 101, Frequency Error 0
<0020> ipaccess-config.c:108 ==> ARFCN 123, Frequency Error -52
where in this case the ARFCN 123 is the BS-11 with a frequency error
larger than all the other (regular) BTS in the vicinity.
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/abis_nm.h | 5 | ||||
-rw-r--r-- | openbsc/include/openbsc/signal.h | 1 | ||||
-rw-r--r-- | openbsc/src/abis_nm.c | 31 | ||||
-rw-r--r-- | openbsc/src/ipaccess-config.c | 73 |
4 files changed, 108 insertions, 2 deletions
diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h index 3dc553144..d8cd9fa78 100644 --- a/openbsc/include/openbsc/abis_nm.h +++ b/openbsc/include/openbsc/abis_nm.h @@ -681,6 +681,11 @@ int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0, u_int8_t e1_port1, u_int8_t ts1); +int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class, + u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr, + u_int8_t test_nr, u_int8_t auton_report, + u_int8_t *phys_config, u_int16_t phys_config_len); + /* Siemens / BS-11 specific */ int abis_nm_bs11_reset_resource(struct gsm_bts *bts); int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin); diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 8f0f8cbd8..1b96a6026 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -58,6 +58,7 @@ enum signal_nm { S_NM_FAIL_REP, /* GSM 12.21 failure event report */ S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */ S_NM_IPACC_NACK, /* GSM 12.21 nanoBTS extensions NM_MT_IPACC_*_*_NACK happened */ + S_NM_TEST_REP, /* GSM 12.21 Test Report */ }; /* SS_LCHAN signals */ diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 0eb8657db..31f1df009 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -801,6 +801,10 @@ static int abis_nm_rcvmsg_report(struct msgb *mb) rx_fail_evt_rep(mb); dispatch_signal(SS_NM, S_NM_FAIL_REP, mb); break; + case NM_MT_TEST_REP: + DEBUGPC(DNM, "Test Report\n"); + dispatch_signal(SS_NM, S_NM_TEST_REP, mb); + break; default: DEBUGPC(DNM, "reporting NM MT 0x%02x\n", mt); break; @@ -1790,6 +1794,33 @@ int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0 return abis_nm_sendmsg(bts, msg); } +/* Chapter 8.7.1 */ +int abis_nm_perform_test(struct gsm_bts *bts, u_int8_t obj_class, + u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr, + u_int8_t test_nr, u_int8_t auton_report, + u_int8_t *phys_config, u_int16_t phys_config_len) +{ + struct abis_om_hdr *oh; + struct msgb *msg = nm_msgb_alloc(); + int len = 4; /* 2 TV attributes */ + + DEBUGP(DNM, "PEFORM TEST\n"); + + if (phys_config_len) + len += 3 + phys_config_len; + + oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); + fill_om_fom_hdr(oh, len, NM_MT_PERF_TEST, + obj_class, bts_nr, trx_nr, ts_nr); + msgb_tv_put(msg, NM_ATT_TEST_NO, test_nr); + msgb_tv_put(msg, NM_ATT_AUTON_REPORT, auton_report); + if (phys_config_len) + msgb_tl16v_put(msg, NM_ATT_PHYS_CONF, phys_config_len, + phys_config); + + return abis_nm_sendmsg(bts, msg); +} + int abis_nm_event_reports(struct gsm_bts *bts, int on) { if (on == 0) diff --git a/openbsc/src/ipaccess-config.c b/openbsc/src/ipaccess-config.c index 5ccbaa70c..a7fb9c43b 100644 --- a/openbsc/src/ipaccess-config.c +++ b/openbsc/src/ipaccess-config.c @@ -38,9 +38,11 @@ #include <openbsc/e1_input.h> #include <openbsc/abis_nm.h> #include <openbsc/signal.h> +#include <openbsc/debug.h> static struct gsm_network *gsmnet; +static int net_listen; static int restart; static char *prim_oml_ip; static char *unit_id; @@ -66,12 +68,61 @@ static int ipacc_msg_nack(int mt) return 0; } +struct ipacc_ferr_elem { + int16_t freq_err; + u_int8_t freq_qual; + u_int8_t arfcn; +} __attribute__((packed)); + +static int test_rep(void *_msg) +{ + struct msgb *msg = _msg; + struct abis_om_fom_hdr *foh = msgb_l3(msg); + u_int16_t test_rep_len, ferr_list_len; + struct ipacc_ferr_elem *ife; + int i; + + DEBUGP(DNM, "TEST REPORT: "); + + if (foh->data[0] != NM_ATT_TEST_NO || + foh->data[2] != NM_ATT_TEST_REPORT) + return -EINVAL; + + DEBUGPC(DNM, "test_no=0x%02x ", foh->data[1]); + /* data[2] == NM_ATT_TEST_REPORT */ + /* data[3..4]: test_rep_len */ + test_rep_len = ntohs(*(u_int16_t *) &foh->data[3]); + /* data[5]: ip.access test result */ + DEBUGPC(DNM, "test_res=%u\n", foh->data[5]); + + /* data[6]: ip.access nested IE. 3 == freq_err_list */ + switch (foh->data[6]) { + case 3: + /* data[7..8]: length of ferr_list */ + ferr_list_len = ntohs(*(u_int16_t *) &foh->data[7]); + + /* data[9...]: frequency error list elements */ + for (i = 0; i < ferr_list_len; i+= sizeof(*ife)) { + ife = (struct ipacc_ferr_elem *) (foh->data + 9 + i); + DEBUGP(DNM, "==> ARFCN %4u, Frequency Error %6hd\n", + ife->arfcn, ntohs(ife->freq_err)); + } + break; + default: + break; + } + + return 0; +} + static int nm_sig_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) { switch (signal) { case S_NM_IPACC_NACK: return ipacc_msg_nack((int)signal_data); + case S_NM_TEST_REP: + return test_rep(signal_data); default: break; } @@ -141,6 +192,9 @@ static void bootstrap_om(struct gsm_bts *bts) printf("restarting BTS\n"); abis_nm_ipaccess_restart(bts); } + + if (net_listen) { + } } void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) @@ -170,6 +224,16 @@ void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx) int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, struct gsm_nm_state *old_state, struct gsm_nm_state *new_state) { + if (evt == EVT_STATECHG_OPER && + obj_class == NM_OC_RADIO_CARRIER && + new_state->availability == 3 && + net_listen) { + struct gsm_bts_trx *trx = obj; + u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 }; + abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff, + NM_IPACC_TESTNO_FREQ_SYNC, 1, + phys_config, sizeof(phys_config)); + } return 0; } @@ -183,7 +247,8 @@ static void print_help(void) printf(" -u --unit-id UNIT_ID\n"); printf(" -o --oml-ip ip\n"); printf(" -r --restart\n"); - printf(" -n flags/mask Set NVRAM attributes.\n"); + printf(" -n flags/mask\tSet NVRAM attributes.\n"); + printf(" -l --listen\tPerform Frequency Error test\n"); printf(" -h --help this text\n"); } @@ -205,9 +270,10 @@ int main(int argc, char **argv) { "oml-ip", 1, 0, 'o' }, { "restart", 0, 0, 'r' }, { "help", 0, 0, 'h' }, + { "listen", 0, 0, 'l' }, }; - c = getopt_long(argc, argv, "u:o:rn:h", long_options, + c = getopt_long(argc, argv, "u:o:rn:lh", long_options, &option_index); if (c == -1) @@ -232,6 +298,9 @@ int main(int argc, char **argv) ul = strtoul(slash+1, NULL, 16); nv_mask = ul & 0xffff; break; + case 'l': + net_listen = 1; + break; case 'h': print_usage(); print_help(); |