From 549faada213f3a446e6cf7d008c0e36cf8bf1c53 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 5 Mar 2010 19:36:20 +0100 Subject: move ip.access netowrk listen (NWL) to network_listen.c Also, we now re-start the network listen test after it has finished, so if you run a test from ipaccess-find, the test will get re-started and re-started all the time. --- openbsc/include/openbsc/Makefile.am | 2 +- openbsc/include/openbsc/abis_nm.h | 2 +- openbsc/include/openbsc/gsm_data.h | 3 + openbsc/include/openbsc/network_listen.h | 12 +++ openbsc/include/openbsc/signal.h | 6 ++ openbsc/src/abis_nm.c | 2 +- openbsc/src/ipaccess/Makefile.am | 2 +- openbsc/src/ipaccess/ipaccess-config.c | 96 +++-------------- openbsc/src/ipaccess/network_listen.c | 172 +++++++++++++++++++++++++++++++ 9 files changed, 213 insertions(+), 84 deletions(-) create mode 100644 openbsc/include/openbsc/network_listen.h create mode 100644 openbsc/src/ipaccess/network_listen.c diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 2ef1ba8a7..e55a83c1e 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -10,7 +10,7 @@ noinst_HEADERS = abis_nm.h abis_rsl.h db.h gsm_04_08.h gsm_data.h \ crc24.h gprs_bssgp.h gprs_llc.h gprs_ns.h gprs_gmm.h \ gb_proxy.h gprs_sgsn.h gsm_04_08_gprs.h sgsn.h \ gprs_ns_frgre.h auth.h osmo_msc.h bsc_msc.h bsc_nat.h \ - osmo_bsc_rf.h osmo_bsc.h + osmo_bsc_rf.h osmo_bsc.h network_listen.h openbsc_HEADERS = gsm_04_08.h meas_rep.h bsc_api.h openbscdir = $(includedir)/openbsc diff --git a/openbsc/include/openbsc/abis_nm.h b/openbsc/include/openbsc/abis_nm.h index b3bf27e9b..13c074686 100644 --- a/openbsc/include/openbsc/abis_nm.h +++ b/openbsc/include/openbsc/abis_nm.h @@ -107,7 +107,7 @@ int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0 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); + const u_int8_t *phys_config, u_int16_t phys_config_len); int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 36591cffa..5ec4441be 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -379,6 +379,9 @@ struct gsm_bts_trx { struct gsm_nm_state nm_state; } pa; } bs11; + struct { + unsigned int test_state; + } ipaccess; }; struct gsm_bts_trx_ts ts[TRX_NR_TS]; }; diff --git a/openbsc/include/openbsc/network_listen.h b/openbsc/include/openbsc/network_listen.h new file mode 100644 index 000000000..afd0049b7 --- /dev/null +++ b/openbsc/include/openbsc/network_listen.h @@ -0,0 +1,12 @@ +#ifndef _OPENBSC_NWL_H +#define _OPENBSC_NWL_H + +#include +#include + +void ipac_nwl_init(void); + +/* Start a NWL test. It will raise the S_IPAC_TEST_COMPLETE signal. */ +int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr); + +#endif /* _OPENBSC_NWL_H */ diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index e614ee50d..49ae37402 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -43,6 +43,7 @@ enum signal_subsystems { SS_GLOBAL, SS_CHALLOC, SS_NS, + SS_IPAC_NWL, }; /* SS_PAGING signals */ @@ -114,6 +115,11 @@ enum signal_scall { S_SCALL_DETACHED, }; +/* SS_IPAC_NWL signals */ +enum signal_ipaccess { + S_IPAC_NWL_COMPLETE, +}; + enum signal_global { S_GLOBAL_SHUTDOWN, }; diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 6f112e189..f7fac6325 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -2121,7 +2121,7 @@ int abis_nm_conn_mdrop_link(struct gsm_bts *bts, u_int8_t e1_port0, u_int8_t ts0 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) + const u_int8_t *phys_config, u_int16_t phys_config_len) { struct abis_om_hdr *oh; struct msgb *msg = nm_msgb_alloc(); diff --git a/openbsc/src/ipaccess/Makefile.am b/openbsc/src/ipaccess/Makefile.am index 533932142..a7fc93fb1 100644 --- a/openbsc/src/ipaccess/Makefile.am +++ b/openbsc/src/ipaccess/Makefile.am @@ -6,7 +6,7 @@ sbin_PROGRAMS = ipaccess-find ipaccess-config ipaccess-proxy ipaccess_find_SOURCES = ipaccess-find.c -ipaccess_config_SOURCES = ipaccess-config.c ipaccess-firmware.c +ipaccess_config_SOURCES = ipaccess-config.c ipaccess-firmware.c network_listen.c ipaccess_config_LDADD = $(top_builddir)/src/libbsc.a $(top_builddir)/src/libmsc.a \ $(top_builddir)/src/libbsc.a $(top_builddir)/src/libvty.a -ldl -ldbi $(LIBCRYPT) diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c index cc966d3f6..72bccf918 100644 --- a/openbsc/src/ipaccess/ipaccess-config.c +++ b/openbsc/src/ipaccess/ipaccess-config.c @@ -44,6 +44,7 @@ #include #include #include +#include #include static struct gsm_network *gsmnet; @@ -115,81 +116,17 @@ static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts_trx *trx) return 0; } -struct ipacc_ferr_elem { - int16_t freq_err; - u_int8_t freq_qual; - u_int8_t arfcn; -} __attribute__((packed)); - -struct ipacc_cusage_elem { - u_int16_t arfcn:10, - rxlev:6; -} __attribute__ ((packed)); - -static int test_rep(void *_msg) +static int nwl_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) { - 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; - struct ipac_bcch_info binfo; - int i, rc; - - 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=%s\n", ipacc_testres_name(foh->data[5])); - - /* data[6]: ip.access nested IE. 3 == freq_err_list */ - switch (foh->data[6]) { - case NM_IPAC_EIE_FREQ_ERR_LIST: - /* 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; - case NM_IPAC_EIE_CHAN_USE_LIST: - /* data[7..8]: length of ferr_list */ - ferr_list_len = ntohs(*(u_int16_t *) &foh->data[7]); - - /* data[9...]: channel usage list elements */ - for (i = 0; i < ferr_list_len; i+= 2) { - u_int16_t *cu_ptr = (u_int16_t *)(foh->data + 9 + i); - u_int16_t cu = ntohs(*cu_ptr); - DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n", - cu & 0x3ff, cu >> 10); - } - break; - case NM_IPAC_EIE_BCCH_INFO_TYPE: - break; - case NM_IPAC_EIE_BCCH_INFO: - rc = ipac_parse_bcch_info(&binfo, foh->data+6); - if (rc < 0) { - DEBUGP(DNM, "BCCH Info parsing failed\n"); - break; - } - DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %3d-%d, LAC %d CI %d\n", - binfo.arfcn, binfo.rx_lev, binfo.rx_qual, - binfo.cgi.mcc, binfo.cgi.mnc, - binfo.cgi.lac, binfo.cgi.ci); - break; - default: + struct gsm_bts_trx *trx; + + switch (signal) { + case S_IPAC_NWL_COMPLETE: + trx = signal_data; + ipac_nwl_test_start(trx, net_listen_testnr); break; } - return 0; } @@ -205,8 +142,6 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, case S_NM_IPACC_ACK: ipacc_data = signal_data; return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx); - case S_NM_TEST_REP: - return test_rep(signal_data); case S_NM_IPACC_RESTART_ACK: printf("The BTS has acked the restart. Exiting.\n"); exit(0); @@ -505,12 +440,9 @@ int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj, new_state->availability == 3) { struct gsm_bts_trx *trx = obj; - if (net_listen_testnr) { - u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 }; - abis_nm_perform_test(trx->bts, 2, 0, trx->nr, 0xff, - net_listen_testnr, 1, - phys_config, sizeof(phys_config)); - } else if (software) { + if (net_listen_testnr) + ipac_nwl_test_start(trx, net_listen_testnr); + else if (software) { int rc; printf("Attempting software upload with '%s'\n", software); rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx); @@ -861,6 +793,10 @@ int main(int argc, char **argv) bts->oml_tei = stream_id; register_signal_handler(SS_NM, nm_sig_cb, NULL); + register_signal_handler(SS_IPAC_NWL, nwl_sig_cb, NULL); + + ipac_nwl_init(); + printf("Trying to connect to ip.access BTS ...\n"); memset(&sin, 0, sizeof(sin)); diff --git a/openbsc/src/ipaccess/network_listen.c b/openbsc/src/ipaccess/network_listen.c new file mode 100644 index 000000000..f64f44ec1 --- /dev/null +++ b/openbsc/src/ipaccess/network_listen.c @@ -0,0 +1,172 @@ +/* ip.access nanoBTS network listen mode */ + +/* (C) 2009-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +enum ipac_test_state { + IPAC_TEST_S_IDLE, + IPAC_TEST_S_RQD, + IPAC_TEST_S_EXEC, + IPAC_TEST_S_PARTIAL, +}; + +int ipac_nwl_test_start(struct gsm_bts_trx *trx, uint8_t testnr) +{ + const uint8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 }; + + if (trx->ipaccess.test_state != IPAC_TEST_S_IDLE) { + fprintf(stderr, "Cannot start test in state %u\n", trx->ipaccess.test_state); + return -EINVAL; + } + + abis_nm_perform_test(trx->bts, 2, 0, trx->nr, 0xff, testnr, 1, + phys_config, sizeof(phys_config)); + + /* FIXME: start safety timer until when test is supposed to complete */ + + return 0; +} + +struct ipacc_ferr_elem { + int16_t freq_err; + uint8_t freq_qual; + uint8_t arfcn; +} __attribute__((packed)); + +struct ipacc_cusage_elem { + uint16_t arfcn:10, + rxlev:6; +} __attribute__ ((packed)); + +static int test_rep(void *_msg) +{ + struct msgb *msg = _msg; + struct abis_om_fom_hdr *foh = msgb_l3(msg); + uint16_t test_rep_len, ferr_list_len; + struct ipacc_ferr_elem *ife; + struct ipac_bcch_info binfo; + int i, rc; + + 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(*(uint16_t *) &foh->data[3]); + /* data[5]: ip.access test result */ + DEBUGPC(DNM, "tst_res=%s\n", ipacc_testres_name(foh->data[5])); + + /* data[6]: ip.access nested IE. 3 == freq_err_list */ + switch (foh->data[6]) { + case NM_IPAC_EIE_FREQ_ERR_LIST: + /* data[7..8]: length of ferr_list */ + ferr_list_len = ntohs(*(uint16_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; + case NM_IPAC_EIE_CHAN_USE_LIST: + /* data[7..8]: length of ferr_list */ + ferr_list_len = ntohs(*(uint16_t *) &foh->data[7]); + + /* data[9...]: channel usage list elements */ + for (i = 0; i < ferr_list_len; i+= 2) { + uint16_t *cu_ptr = (uint16_t *)(foh->data + 9 + i); + uint16_t cu = ntohs(*cu_ptr); + DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n", + cu & 0x3ff, cu >> 10); + } + break; + case NM_IPAC_EIE_BCCH_INFO_TYPE: + break; + case NM_IPAC_EIE_BCCH_INFO: + rc = ipac_parse_bcch_info(&binfo, foh->data+6); + if (rc < 0) { + DEBUGP(DNM, "BCCH Info parsing failed\n"); + break; + } + DEBUGP(DNM, "==> ARFCN %u, RxLev %2u, RxQual %2u: %3d-%d, LAC %d CI %d\n", + binfo.arfcn, binfo.rx_lev, binfo.rx_qual, + binfo.cgi.mcc, binfo.cgi.mnc, + binfo.cgi.lac, binfo.cgi.ci); + break; + default: + break; + } + + switch (foh->data[5]) { + case NM_IPACC_TESTRES_SUCCESS: + case NM_IPACC_TESTRES_STOPPED: + case NM_IPACC_TESTRES_TIMEOUT: + case NM_IPACC_TESTRES_NO_CHANS: + msg->trx->ipaccess.test_state = IPAC_TEST_S_IDLE; + /* Send signal to notify higher layers of test completion */ + dispatch_signal(SS_IPAC_NWL, S_IPAC_NWL_COMPLETE, msg->trx); + break; + case NM_IPACC_TESTRES_PARTIAL: + msg->trx->ipaccess.test_state = IPAC_TEST_S_PARTIAL; + break; + } + + return 0; +} + +static int nwl_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct ipacc_ack_signal_data *ipacc_data; + + switch (signal) { + case S_NM_TEST_REP: + return test_rep(signal_data); + default: + break; + } + + return 0; +} + +void ipac_nwl_init(void) +{ + register_signal_handler(SS_NM, nwl_sig_cb, NULL); +} -- cgit v1.2.3