From cdf76cff9f06f4c0ee98207862648334425e211a Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 5 Aug 2011 21:23:46 +0200 Subject: GPRS: Fix the parsing/interpretation of the PDP CTX status IE The byte ordering is a bit odd: The least significant byte is ahead of the most significant byte, different from everything else in GSM that seems to be big-endian. Thanks to Seungju Kim for repoerting the bug. --- openbsc/src/gprs/gprs_gmm.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c index 098e4c25b..c9fe5172e 100644 --- a/openbsc/src/gprs/gprs_gmm.c +++ b/openbsc/src/gprs/gprs_gmm.c @@ -867,7 +867,7 @@ static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause) } static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx, - uint16_t pdp_status) + uint8_t *pdp_status) { struct sgsn_pdp_ctx *pdp, *pdp2; /* 24.008 4.7.5.1.3: If the PDP context status information element is @@ -878,11 +878,20 @@ static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx, * being in state PDP-INACTIVE. */ llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) { - if (!(pdp_status & (1 << pdp->nsapi))) { - LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u " - "due to PDP CTX STATUS IE= 0x%04x\n", - pdp->nsapi, pdp_status); - sgsn_delete_pdp_ctx(pdp); + if (pdp->nsapi < 8) { + if (!(pdp_status[0] & (1 << pdp->nsapi))) { + LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u " + "due to PDP CTX STATUS IE= 0x%02x%02x\n", + pdp->nsapi, pdp_status[1], pdp_status[0]); + sgsn_delete_pdp_ctx(pdp); + } + } else { + if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) { + LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u " + "due to PDP CTX STATUS IE= 0x%02x%02x\n", + pdp->nsapi, pdp_status[1], pdp_status[0]); + sgsn_delete_pdp_ctx(pdp); + } } } } @@ -975,8 +984,7 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, /* Look at PDP Context Status IE and see if MS's view of * activated/deactivated NSAPIs agrees with our view */ if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) { - uint16_t pdp_status = ntohs(*(uint16_t *) - TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)); + uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS); process_ms_ctx_status(mmctx, pdp_status); } -- cgit v1.2.3 From 0b69bc34d78073c568c03bf59af3d36e8ff057e6 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 9 Aug 2011 11:21:23 +0200 Subject: DAHDI: Fix case where we have multiple E1 ports/cards (spans) DAHDI creates one device node for every E1 timeslot, starting from '1', and keeps incrementing that number even for additional ports/cards. Thus, we have to use the e1inp_line number multiplied by 31 as a base. --- openbsc/src/libabis/input/dahdi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/input/dahdi.c b/openbsc/src/libabis/input/dahdi.c index 6f8983763..a7b45a1af 100644 --- a/openbsc/src/libabis/input/dahdi.c +++ b/openbsc/src/libabis/input/dahdi.c @@ -421,11 +421,17 @@ static int dahdi_e1_setup(struct e1inp_line *line) char openstr[128]; struct e1inp_ts *e1i_ts = &line->ts[idx]; struct osmo_fd *bfd = &e1i_ts->driver.dahdi.fd; + int dev_nr; + + /* DAHDI device names/numbers just keep incrementing + * even over multiple boards. So TS1 of the second + * board will be 32 */ + dev_nr = line->num * (NUM_E1_TS-1) + ts; bfd->data = line; bfd->priv_nr = ts; bfd->cb = dahdi_fd_cb; - snprintf(openstr, sizeof(openstr), "/dev/dahdi/%d", ts); + snprintf(openstr, sizeof(openstr), "/dev/dahdi/%d", dev_nr); switch (e1i_ts->type) { case E1INP_TS_TYPE_NONE: -- cgit v1.2.3 From 52a0b12fe184efbdc9ad22ca5a392a49a22af8b2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 9 Aug 2011 21:24:47 +0200 Subject: LAPD: Remove all calls to 'assert' from the code For a system-level daemon, no protocol parser error should ever call assert, which would take down the entire process. --- openbsc/src/libabis/input/lapd.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/input/lapd.c b/openbsc/src/libabis/input/lapd.c index d0fab1815..0d269cd41 100644 --- a/openbsc/src/libabis/input/lapd.c +++ b/openbsc/src/libabis/input/lapd.c @@ -31,7 +31,6 @@ #include #include -#include #include #include "lapd.h" @@ -353,14 +352,20 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len nr = -1; if ((data[2] & 1) == 0) { typ = LAPD_TYPE_I; - assert(len >= 4); + if (len < 4) { + LOGP(DMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len); + return NULL; + } ns = data[2] >> 1; nr = data[3] >> 1; pf = data[3] & 1; cmd = LAPD_CMD_I; } else if ((data[2] & 3) == 1) { typ = LAPD_TYPE_S; - assert(len >= 4); + if (len < 4) { + LOGP(DMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len); + return NULL; + } nr = data[3] >> 1; pf = data[3] & 1; switch (data[2]) { @@ -445,7 +450,9 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len DEBUGP(DMI, "DOUBLE FRAME, ignoring\n"); cmd = 0; // ignore } else { - assert(0); + LOGP(DMI, LOGL_ERROR, "LAPD: Out of order " + "ns %d != vr %d, ignoring\n", ns, sap->vr); + return NULL; }; } else { //printf("IN SEQUENCE\n"); -- cgit v1.2.3 From 6e4c26aa08f4ba32749292ebdd13af3320a93d0f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 9 Aug 2011 21:41:35 +0200 Subject: LAPD: Use proper log levels and prefix all messages with LAPD --- openbsc/src/libabis/input/lapd.c | 51 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 24 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/input/lapd.c b/openbsc/src/libabis/input/lapd.c index 0d269cd41..66ff05e09 100644 --- a/openbsc/src/libabis/input/lapd.c +++ b/openbsc/src/libabis/input/lapd.c @@ -189,7 +189,7 @@ static struct lapd_tei *teip_from_tei(struct lapd_instance *li, uint8_t tei) static void lapd_tei_set_state(struct lapd_tei *teip, int newstate) { - DEBUGP(DMI, "state change on TEI %d: %s -> %s\n", teip->tei, + LOGP(DMI, LOGL_INFO, "LAPD state change on TEI %d: %s -> %s\n", teip->tei, lapd_tei_states[teip->state], lapd_tei_states[newstate]); teip->state = newstate; }; @@ -233,7 +233,7 @@ static struct lapd_sap *lapd_sap_alloc(struct lapd_tei *teip, uint8_t sapi) { struct lapd_sap *sap = talloc_zero(teip, struct lapd_sap); - LOGP(DMI, LOGL_INFO, "Allocating SAP for SAPI=%u / TEI=%u\n", + LOGP(DMI, LOGL_INFO, "LAPD Allocating SAP for SAPI=%u / TEI=%u\n", sapi, teip->tei); sap->sapi = sapi; @@ -253,8 +253,9 @@ static void lapd_sap_set_state(struct lapd_tei *teip, uint8_t sapi, if (!sap) return; - DEBUGP(DMI, "state change on TEI %u / SAPI %u: %s -> %s\n", teip->tei, - sapi, lapd_sap_states[sap->state], lapd_sap_states[newstate]); + LOGP(DMI, LOGL_INFO, "LAPD state change on TEI %u / SAPI %u: " + "%s -> %s\n", teip->tei, sapi, + lapd_sap_states[sap->state], lapd_sap_states[newstate]); switch (sap->state) { case SAP_STATE_SABM_RETRANS: if (newstate != SAP_STATE_SABM_RETRANS) @@ -280,11 +281,12 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len) uint8_t resp[8]; struct lapd_tei *teip; - DEBUGP(DMI, "TEIMGR: entity %x, ref %x, mt %x, action %x, e %x\n", entity, ref, mt, action, e); + DEBUGP(DMI, "LAPD TEIMGR: entity %x, ref %x, mt %x, action %x, e %x\n", + entity, ref, mt, action, e); switch (mt) { case 0x01: /* IDENTITY REQUEST */ - DEBUGP(DMI, "TEIMGR: identity request for TEI %u\n", action); + DEBUGP(DMI, "LAPD TEIMGR: identity request for TEI %u\n", action); teip = teip_from_tei(li, action); if (!teip) { @@ -301,7 +303,7 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len) lapd_tei_set_state(teip, LAPD_TEI_ASSIGNED); break; default: - LOGP(DMI, LOGL_NOTICE, "TEIMGR: unknown mt %x action %x\n", + LOGP(DMI, LOGL_NOTICE, "LAPD TEIMGR: unknown mt %x action %x\n", mt, action); break; }; @@ -324,13 +326,13 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len *prim = 0; if (len < 2) { - DEBUGP(DMI, "len %d < 2\n", len); + LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 2, ignoring\n", len); return NULL; }; if ((data[0] & 1) != 0 || (data[1] & 1) != 1) { - DEBUGP(DMI, "address field %x/%x not well formed\n", data[0], - data[1]); + LOGP(DMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n", + data[0], data[1]); return NULL; }; @@ -341,7 +343,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len //DEBUGP(DMI, " address sapi %x tei %d cmd %d cr %d\n", sapi, tei, command, cr); if (len < 3) { - DEBUGP(DMI, "len %d < 3\n", len); + LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len); return NULL; }; @@ -379,7 +381,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len cmd = LAPD_CMD_REJ; break; default: - LOGP(DMI, LOGL_ERROR, "unknown LAPD S cmd %x\n", data[2]); + LOGP(DMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]); return NULL; }; } else if ((data[2] & 3) == 3) { @@ -410,7 +412,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len break; default: - LOGP(DMI, LOGL_ERROR, "unknown U cmd %x " + LOGP(DMI, LOGL_ERROR, "LAPD unknown U cmd %x " "(pf %x data %x)\n", val, pf, data[2]); return NULL; }; @@ -426,13 +428,13 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len teip = teip_from_tei(li, tei); if (!teip) { - LOGP(DMI, LOGL_NOTICE, "Unknown TEI %u\n", tei); + LOGP(DMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei); return NULL; } sap = lapd_sap_find(teip, sapi); if (!sap) { - LOGP(DMI, LOGL_INFO, "No SAP for TEI=%u / SAPI=%u, " + LOGP(DMI, LOGL_INFO, "LAPD No SAP for TEI=%u / SAPI=%u, " "allocating\n", tei, sapi); sap = lapd_sap_alloc(teip, sapi); } @@ -445,12 +447,13 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len switch (cmd) { case LAPD_CMD_I: if (ns != sap->vr) { - DEBUGP(DMI, "ns %d != vr %d\n", ns, sap->vr); + DEBUGP(DMI, "LAPD ns %d != vr %d\n", ns, sap->vr); if (ns == ((sap->vr - 1) & 0x7f)) { - DEBUGP(DMI, "DOUBLE FRAME, ignoring\n"); + LOGP(DMI, LOGL_NOTICE, "LAPD double frame, " + "ignoring\n"); cmd = 0; // ignore } else { - LOGP(DMI, LOGL_ERROR, "LAPD: Out of order " + LOGP(DMI, LOGL_ERROR, "LAPD Out of order " "ns %d != vr %d, ignoring\n", ns, sap->vr); return NULL; }; @@ -567,7 +570,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len */ /* interrogating us, send rr */ - DEBUGP(DMI, "Sending RR response\n"); + DEBUGP(DMI, "LAPD Sending RR response\n"); resp[l++] = data[0]; resp[l++] = (tei << 1) | 1; resp[l++] = 0x01; // rr @@ -594,7 +597,7 @@ static int lapd_send_sabm(struct lapd_instance *li, uint8_t tei, uint8_t sapi) if (!msg) return -ENOMEM; - DEBUGP(DMI, "Sending SABM for TEI=%u, SAPI=%u\n", tei, sapi); + LOGP(DMI, LOGL_INFO, "LAPD Sending SABM for TEI=%u, SAPI=%u\n", tei, sapi); msgb_put_u8(msg, (sapi << 2) | (li->network_side ? 2 : 0)); msgb_put_u8(msg, (tei << 1) | 1); @@ -669,15 +672,15 @@ void lapd_transmit(struct lapd_instance *li, uint8_t tei, uint8_t sapi, struct lapd_sap *sap; if (!teip) { - LOGP(DMI, LOGL_ERROR, "Cannot transmit on non-existing " - "TEI %u\n", tei); + LOGP(DMI, LOGL_ERROR, "LAPD Cannot transmit on " + "non-existing TEI %u\n", tei); return; } sap = lapd_sap_find(teip, sapi); if (!sap) { - LOGP(DMI, LOGL_INFO, "Tx on unknown SAPI=%u in TEI=%u, " - "allocating\n", sapi, tei); + LOGP(DMI, LOGL_INFO, "LAPD Tx on unknown SAPI=%u " + "in TEI=%u, allocating\n", sapi, tei); sap = lapd_sap_alloc(teip, sapi); } -- cgit v1.2.3 From e5215b539845b8058de129df8724045723b883b0 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 9 Aug 2011 21:53:20 +0200 Subject: 04.08 / MNCC: elevate error messages to LOGL_ERROR this way you can actually see them... --- openbsc/src/libmsc/gsm_04_08.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index a6ed3e83e..ff012246d 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1602,7 +1602,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) remote_bts->nr, remote_lchan->ts->trx->nr, remote_lchan->ts->nr); if (bts->type != remote_bts->type) { - DEBUGP(DCC, "Cannot switch calls between different BTS types yet\n"); + LOGP(DCC, LOGL_ERROR, "Cannot switch calls between different BTS types yet\n"); return -EINVAL; } @@ -1637,7 +1637,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) trau_mux_map_lchan(lchan, remote_lchan); break; default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); return -EINVAL; } @@ -1680,7 +1680,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) switch (bts->type) { case GSM_BTS_TYPE_NANOBTS: if (ipacc_rtp_direct) { - DEBUGP(DCC, "Error: RTP proxy is disabled\n"); + LOGP(DCC, LOGL_ERROR, "Error: RTP proxy is disabled\n"); return -EINVAL; } /* in case, we don't have a RTP socket yet, we note this @@ -1709,7 +1709,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) return trau_mux_unmap(NULL, callref); break; default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); return -EINVAL; } @@ -2991,7 +2991,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) case GSM_BTS_TYPE_RBS2000: return trau_send_frame(trans->conn->lchan, arg); default: - DEBUGP(DCC, "Unknown BTS type %u\n", bts->type); + LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); } return -EINVAL; } -- cgit v1.2.3 From 166460247619c39204139aa1c474a41871897282 Mon Sep 17 00:00:00 2001 From: Dieter Spaar Date: Thu, 28 Jul 2011 00:01:50 +0200 Subject: Initial version of Support for Nokia *Site BTS This includes the MetroSite, but also other Nokia BTS models. --- .../osmo-nitb/nokia/openbsc_nokia_3trx.cfg | 118 ++ openbsc/include/openbsc/abis_rsl.h | 7 + openbsc/include/openbsc/bss.h | 1 + openbsc/include/openbsc/gsm_data_shared.h | 1 + openbsc/src/libbsc/Makefile.am | 1 + openbsc/src/libbsc/abis_rsl.c | 53 + openbsc/src/libbsc/bsc_init.c | 29 + openbsc/src/libbsc/bts_init.c | 1 + openbsc/src/libbsc/bts_nokia_site.c | 1949 ++++++++++++++++++++ openbsc/src/libbsc/system_information.c | 2 +- openbsc/src/libcommon/gsm_data.c | 1 + openbsc/src/libmsc/gsm_04_08.c | 1 + 12 files changed, 2163 insertions(+), 1 deletion(-) create mode 100644 openbsc/doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg create mode 100644 openbsc/src/libbsc/bts_nokia_site.c (limited to 'openbsc') diff --git a/openbsc/doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg b/openbsc/doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg new file mode 100644 index 000000000..a7d980f7e --- /dev/null +++ b/openbsc/doc/examples/osmo-nitb/nokia/openbsc_nokia_3trx.cfg @@ -0,0 +1,118 @@ +! +! OpenBSC configuration saved from vty +! ! +password foo +! +line vty + no login +! +e1_input + e1_line 0 driver misdn +network + network country code 1 + mobile network code 1 + short name OpenBSC + long name OpenBSC + auth policy accept-all + timer t3101 10 + timer t3113 60 + bts 0 + type nokia_site + band GSM1800 + cell_identity 1 + location_area_code 1 + base_station_id_code 63 + training_sequence_code 7 + + oml e1 line 0 timeslot 1 sub-slot full + oml e1 tei 1 + + trx 0 + arfcn 866 + max_power_red 24 + rsl e1 line 0 timeslot 2 sub-slot full + rsl e1 tei 1 + timeslot 0 + phys_chan_config CCCH+SDCCH4 + e1 line 0 timeslot 6 sub-slot full + timeslot 1 + phys_chan_config SDCCH8 + e1 line 0 timeslot 6 sub-slot 1 + timeslot 2 + phys_chan_config TCH/F + e1 line 0 timeslot 6 sub-slot 2 + timeslot 3 + phys_chan_config TCH/F + e1 line 0 timeslot 6 sub-slot 3 + timeslot 4 + phys_chan_config TCH/F + e1 line 0 timeslot 7 sub-slot 0 + timeslot 5 + phys_chan_config TCH/F + e1 line 0 timeslot 7 sub-slot 1 + timeslot 6 + phys_chan_config TCH/F + e1 line 0 timeslot 7 sub-slot 2 + timeslot 7 + phys_chan_config TCH/F + e1 line 0 timeslot 7 sub-slot 3 + + trx 1 + arfcn 870 + max_power_red 24 + rsl e1 line 0 timeslot 3 sub-slot full + rsl e1 tei 2 + timeslot 0 + phys_chan_config TCH/F + e1 line 0 timeslot 8 sub-slot 0 + timeslot 1 + phys_chan_config TCH/F + e1 line 0 timeslot 8 sub-slot 1 + timeslot 2 + phys_chan_config TCH/F + e1 line 0 timeslot 8 sub-slot 2 + timeslot 3 + phys_chan_config TCH/F + e1 line 0 timeslot 8 sub-slot 3 + timeslot 4 + phys_chan_config TCH/F + e1 line 0 timeslot 9 sub-slot 0 + timeslot 5 + phys_chan_config TCH/F + e1 line 0 timeslot 9 sub-slot 1 + timeslot 6 + phys_chan_config TCH/F + e1 line 0 timeslot 9 sub-slot 2 + timeslot 7 + phys_chan_config TCH/F + e1 line 0 timeslot 9 sub-slot 3 + + trx 2 + arfcn 874 + max_power_red 24 + rsl e1 line 0 timeslot 4 sub-slot full + rsl e1 tei 3 + timeslot 0 + phys_chan_config TCH/F + e1 line 0 timeslot 10 sub-slot 0 + timeslot 1 + phys_chan_config TCH/F + e1 line 0 timeslot 10 sub-slot 1 + timeslot 2 + phys_chan_config TCH/F + e1 line 0 timeslot 10 sub-slot 2 + timeslot 3 + phys_chan_config TCH/F + e1 line 0 timeslot 10 sub-slot 3 + timeslot 4 + phys_chan_config TCH/F + e1 line 0 timeslot 11 sub-slot 0 + timeslot 5 + phys_chan_config TCH/F + e1 line 0 timeslot 11 sub-slot 1 + timeslot 6 + phys_chan_config TCH/F + e1 line 0 timeslot 11 sub-slot 2 + timeslot 7 + phys_chan_config TCH/F + e1 line 0 timeslot 11 sub-slot 3 diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 3b4df90c0..bf1df5e0e 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -90,5 +90,12 @@ int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm); int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number, uint8_t cb_command, const uint8_t *data, int len); +/* some Nokia specific stuff */ +int rsl_nokia_si_begin(struct gsm_bts_trx *trx); +int rsl_nokia_si_end(struct gsm_bts_trx *trx); + +/* required for Nokia BTS power control */ +int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction); + #endif /* RSL_MT_H */ diff --git a/openbsc/include/openbsc/bss.h b/openbsc/include/openbsc/bss.h index 05495ddcb..2317bd217 100644 --- a/openbsc/include/openbsc/bss.h +++ b/openbsc/include/openbsc/bss.h @@ -14,4 +14,5 @@ extern int bts_model_bs11_init(void); extern int bts_model_rbs2k_init(void); extern int bts_model_nanobts_init(void); extern int bts_model_hslfemto_init(void); +extern int bts_model_nokia_site_init(void); #endif diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index 011e0aa96..b9829222f 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -325,6 +325,7 @@ enum gsm_bts_type { GSM_BTS_TYPE_NANOBTS, GSM_BTS_TYPE_RBS2000, GSM_BTS_TYPE_HSL_FEMTO, + GSM_BTS_TYPE_NOKIA_SITE, }; struct vty; diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am index 3af4a2a3d..a8e05206c 100644 --- a/openbsc/src/libbsc/Makefile.am +++ b/openbsc/src/libbsc/Makefile.am @@ -11,6 +11,7 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \ bts_ericsson_rbs2000.c \ bts_ipaccess_nanobts.c \ bts_siemens_bs11.c \ + bts_nokia_site.c \ bts_hsl_femtocell.c \ bts_unknown.c \ chan_alloc.c \ diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index d74907b0a..f20b4f2b5 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1108,6 +1108,12 @@ static int abis_rsl_rx_trx(struct msgb *msg) LOGP(DRSL, LOGL_ERROR, "%s CCCH/ACCH/CPU Overload\n", gsm_trx_name(msg->trx)); break; + case 0x42: /* Nokia specific: SI End ACK */ + LOGP(DRSL, LOGL_INFO, "Nokia SI End ACK\n"); + break; + case 0x43: /* Nokia specific: SI End NACK */ + LOGP(DRSL, LOGL_INFO, "Nokia SI End NACK\n"); + break; default: LOGP(DRSL, LOGL_NOTICE, "%s Unknown Abis RSL TRX message " "type 0x%02x\n", gsm_trx_name(msg->trx), rslh->msg_type); @@ -1892,3 +1898,50 @@ int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number, return abis_rsl_sendmsg(cb_cmd); } + +int rsl_nokia_si_begin(struct gsm_bts_trx *trx) +{ + struct abis_rsl_common_hdr *ch; + struct msgb *msg = rsl_msgb_alloc(); + + ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch)); + ch->msg_discr = ABIS_RSL_MDISC_TRX; + ch->msg_type = 0x40; /* Nokia SI Begin */ + + msg->trx = trx; + + return abis_rsl_sendmsg(msg); +} + +int rsl_nokia_si_end(struct gsm_bts_trx *trx) +{ + struct abis_rsl_common_hdr *ch; + struct msgb *msg = rsl_msgb_alloc(); + + ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch)); + ch->msg_discr = ABIS_RSL_MDISC_TRX; + ch->msg_type = 0x41; /* Nokia SI End */ + + msgb_tv_put(msg, 0xFD, 0x00); /* Nokia Pagemode Info, No paging reorganisation required */ + + msg->trx = trx; + + return abis_rsl_sendmsg(msg); +} + +int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction) +{ + struct abis_rsl_common_hdr *ch; + struct msgb *msg = rsl_msgb_alloc(); + + ch = (struct abis_rsl_common_hdr *) msgb_put(msg, sizeof(*ch)); + ch->msg_discr = ABIS_RSL_MDISC_DED_CHAN; + ch->msg_type = RSL_MT_BS_POWER_CONTROL; + + msgb_tv_put(msg, RSL_IE_CHAN_NR, channel); + msgb_tv_put(msg, RSL_IE_BS_POWER, reduction); /* reduction in 2dB steps */ + + msg->trx = trx; + + return abis_rsl_sendmsg(msg); +} diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 02a3adfcc..1d885db37 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -249,8 +249,19 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx) trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code, bsc_gsmnet->network_code, trx->bts->location_area_code, trx->bts->cell_identity, trx->bts->bsic, trx->bts->tsc); + + if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { + rsl_nokia_si_begin(trx); + } + set_system_infos(trx); + if (trx->bts->type == GSM_BTS_TYPE_NOKIA_SITE) { + /* channel unspecific, power reduction in 2 dB steps */ + rsl_bs_power_control(trx, 0xFF, trx->max_power_red / 2); + rsl_nokia_si_end(trx); + } + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) generate_ma_for_ts(&trx->ts[i]); } @@ -268,6 +279,24 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, switch (signal) { case S_INP_TEI_UP: + if (isd->link_type == E1INP_SIGN_OML) { + /* TODO: this is required for the Nokia BTS, hopping is configured + during OML, other MA is not set. */ + struct gsm_bts_trx *cur_trx; + /* was static in system_information.c */ + extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts); + uint8_t ca[20]; + /* has to be called before generate_ma_for_ts to + set bts->si_common.cell_alloc */ + generate_cell_chan_list(ca, trx->bts); + + llist_for_each_entry(cur_trx, &trx->bts->trx_list, list) { + int i; + + for (i = 0; i < ARRAY_SIZE(cur_trx->ts); i++) + generate_ma_for_ts(&cur_trx->ts[i]); + } + } if (isd->link_type == E1INP_SIGN_RSL) bootstrap_rsl(trx); break; diff --git a/openbsc/src/libbsc/bts_init.c b/openbsc/src/libbsc/bts_init.c index 87bdde066..693eca825 100644 --- a/openbsc/src/libbsc/bts_init.c +++ b/openbsc/src/libbsc/bts_init.c @@ -24,6 +24,7 @@ int bts_init(void) bts_model_rbs2k_init(); bts_model_nanobts_init(); bts_model_hslfemto_init(); + bts_model_nokia_site_init(); /* Your new BTS here. */ return 0; } diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c new file mode 100644 index 000000000..d30881bba --- /dev/null +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -0,0 +1,1949 @@ +/* Nokia XXXsite family specific code */ + +/* (C) 2011 by Dieter Spaar + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +/* + TODO: Attention: There are some static variables used for states during + configuration. Those variables have to be moved to a BTS specific context, + otherwise there will most certainly be problems if more than one Nokia BTS + is used. +*/ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include "../libabis/input/lapd.h" + +/* TODO: put in a separate file ? */ + +/* TODO: move statics to BTS context */ +static int do_reset = 1; +/*static*/ int wait_reset = 0; +struct osmo_timer_list reset_timer; /* timer to re-start after reset */ + +#define RESET_INTERVAL 0, 3000000 /* 3 seconds */ + +extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg); +/* was static in system_information.c */ +extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts); + +static void abis_nm_queue_send_next(struct gsm_bts *bts); +static void reset_timer_cb(void *_bts); +static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref); +static int dump_elements(uint8_t *data, int len); + +static void bootstrap_om_bts(struct gsm_bts *bts) +{ + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); + + if(do_reset) + abis_nm_reset(bts, 1); +} + +static void bootstrap_om_trx(struct gsm_bts_trx *trx) +{ + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n", + trx->bts->nr, trx->nr); +} + +static int shutdown_om(struct gsm_bts *bts) +{ + /* TODO !? */ + return 0; +} + +#define SAPI_OML 62 +#define SAPI_RSL 0 + +/* + + Tell LAPD to start start the SAP (send SABM requests) for all signalling + timeslots in this line + + Attention: this has to be adapted for MISDN +*/ + +static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) +{ + struct e1inp_sign_link *link; + int i; + + for (i = 0; i < ARRAY_SIZE(line->ts); i++) { + struct e1inp_ts *ts = &line->ts[i]; + + if (ts->type != E1INP_TS_TYPE_SIGN) + continue; + + llist_for_each_entry(link, &ts->sign.sign_links, list) { + if(sapi != -1 && link->sapi != sapi) + continue; + +#if 0 /* debugging */ + printf("sap start/stop (%d): %d tei=%d sapi=%d\n", start, i + 1, link->tei, link->sapi); +#endif + + if (start) + lapd_sap_start(ts->driver.dahdi.lapd, link->tei, link->sapi); + else + lapd_sap_stop(ts->driver.dahdi.lapd, link->tei, link->sapi); + } + } +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int gbl_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct gsm_bts *bts; + + if (subsys != SS_GLOBAL) + return 0; + + switch (signal) { + case S_GLOBAL_BTS_CLOSE_OM: + bts = signal_data; + if (bts->type == GSM_BTS_TYPE_NOKIA_SITE) + shutdown_om(signal_data); + break; + } + + return 0; +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int inp_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct input_signal_data *isd = signal_data; + + if (subsys != SS_INPUT) + return 0; + + switch (signal) { + case S_INP_LINE_INIT: + start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */ + break; + case S_INP_TEI_DN: + break; + case S_INP_TEI_UP: + switch (isd->link_type) { + case E1INP_SIGN_OML: + if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE) + break; + + if (isd->tei == isd->trx->bts->oml_tei) + bootstrap_om_bts(isd->trx->bts); + else + bootstrap_om_trx(isd->trx); + break; + } + break; + } + + return 0; +} + +static void nm_statechg_evt(unsigned int signal, + struct nm_statechg_signal_data *nsd) +{ + if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE) + return; +} + +static int nm_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + if (subsys != SS_NM) + return 0; + + switch (signal) { + case S_NM_STATECHG_OPER: + case S_NM_STATECHG_ADM: + nm_statechg_evt(signal, signal_data); + break; + default: + break; + } + + return 0; +} + +/* TODO: put in a separate file ? */ + +static char *get_msg_type_name_string(uint8_t msg_type) +{ + switch(msg_type) { + case 0x80: + return "NOKIA_BTS_CONF_DATA"; + case 0x81: + return "NOKIA_BTS_ACK"; + case 0x82: + return "NOKIA_BTS_OMU_STARTED"; + case 0x83: + return "NOKIA_BTS_START_DOWNLOAD_REQ"; + case 0x84: + return "NOKIA_BTS_MF_REQ"; + case 0x85: + return "NOKIA_BTS_AF_REQ"; + case 0x86: + return "NOKIA_BTS_RESET_REQ"; + case 0x87: + return "NOKIA_reserved"; + case 0x88: + return "NOKIA_BTS_CONF_REQ"; + case 0x89: + return "NOKIA_BTS_TEST_REQ"; + case 0x8A: + return "NOKIA_BTS_TEST_REPORT"; + case 0x8B: + return "NOKIA_reserved"; + case 0x8C: + return "NOKIA_reserved"; + case 0x8D: + return "NOKIA_reserved"; + case 0x8E: + return "NOKIA_BTS_CONF_COMPL"; + case 0x8F: + return "NOKIA_reserved"; + case 0x90: + return "NOKIA_BTS_STM_TEST_REQ"; + case 0x91: + return "NOKIA_BTS_STM_TEST_REPORT"; + case 0x92: + return "NOKIA_BTS_TRANSMISSION_COMMAND"; + case 0x93: + return "NOKIA_BTS_TRANSMISSION_ANSWER"; + case 0x94: + return "NOKIA_BTS_HW_DB_UPLOAD_REQ"; + case 0x95: + return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ"; + case 0x96: + return "NOKIA_BTS_HW_DB_SAVE_REQ"; + case 0x97: + return "NOKIA_BTS_FLASH_ERASURE_REQ"; + case 0x98: + return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ"; + case 0x99: + return "NOKIA_BTS_PWR_SUPPLY_CONTROL"; + case 0x9A: + return "NOKIA_BTS_ATTRIBUTE_REQ"; + case 0x9B: + return "NOKIA_BTS_ATTRIBUTE_REPORT"; + case 0x9C: + return "NOKIA_BTS_HW_REQ"; + case 0x9D: + return "NOKIA_BTS_HW_REPORT"; + case 0x9E: + return "NOKIA_BTS_RTE_TEST_REQ"; + case 0x9F: + return "NOKIA_BTS_RTE_TEST_REPORT"; + case 0xA0: + return "NOKIA_BTS_HW_DB_VERIFICATION_REQ"; + case 0xA1: + return "NOKIA_BTS_CLOCK_REQ"; + case 0xA2: + return "NOKIA_AC_CIRCUIT_REQ_NACK"; + case 0xA3: + return "NOKIA_AC_INTERRUPTED"; + case 0xA4: + return "NOKIA_BTS_NEW_TRE_INFO"; + case 0xA5: + return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED"; + case 0xA6: + return "NOKIA_BTS_TRE_POLL_LIST"; + case 0xA7: + return "NOKIA_AC_CIRCUIT_REQ"; + case 0xA8: + return "NOKIA_BTS_BLOCK_CTRL_REQ"; + case 0xA9: + return "NOKIA_BTS_GSM_TIME_REQ"; + case 0xAA: + return "NOKIA_BTS_GSM_TIME"; + case 0xAB: + return "NOKIA_BTS_OUTPUT_CONTROL"; + case 0xAC: + return "NOKIA_BTS_STATE_CHANGED"; + case 0xAD: + return "NOKIA_BTS_SW_SAVE_REQ"; + case 0xAE: + return "NOKIA_BTS_ALARM"; + case 0xAF: + return "NOKIA_BTS_CHA_ADM_STATE"; + case 0xB0: + return "NOKIA_AC_POOL_SIZE_REPORT"; + case 0xB1: + return "NOKIA_AC_POOL_SIZE_INQUIRY"; + case 0xB2: + return "NOKIA_BTS_COMMISS_TEST_COMPLETED"; + case 0xB3: + return "NOKIA_BTS_COMMISS_TEST_REQ"; + case 0xB4: + return "NOKIA_BTS_TRANSP_BTS_TO_BSC"; + case 0xB5: + return "NOKIA_BTS_TRANSP_BSC_TO_BTS"; + case 0xB6: + return "NOKIA_BTS_LCS_COMMAND"; + case 0xB7: + return "NOKIA_BTS_LCS_ANSWER"; + case 0xB8: + return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND"; + case 0xB9: + return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER"; + default: + return "unknown"; + } +} + +static char *get_element_name_string(uint16_t element) +{ + switch(element) { + case 0x01: + return "Ny1"; + case 0x02: + return "T3105_F"; + case 0x03: + return "Interference band limits"; + case 0x04: + return "Interference report timer in secs"; + case 0x05: + return "Channel configuration per TS"; + case 0x06: + return "BSIC"; + case 0x07: + return "RACH report timer in secs"; + case 0x08: + return "Hardware database status"; + case 0x09: + return "BTS RX level"; + case 0x0A: + return "ARFN"; + case 0x0B: + return "STM antenna attenuation"; + case 0x0C: + return "Cell allocation bitmap"; + case 0x0D: + return "Radio definition per TS"; + case 0x0E: + return "Frame number"; + case 0x0F: + return "Antenna diversity"; + case 0x10: + return "T3105_D"; + case 0x11: + return "File format"; + case 0x12: + return "Last File"; + case 0x13: + return "BTS type"; + case 0x14: + return "Erasure mode"; + case 0x15: + return "Hopping mode"; + case 0x16: + return "Floating TRX"; + case 0x17: + return "Power supplies"; + case 0x18: + return "Reset type"; + case 0x19: + return "Averaging period"; + case 0x1A: + return "RBER2"; + case 0x1B: + return "LAC"; + case 0x1C: + return "CI"; + case 0x1D: + return "Failure parameters"; + case 0x1E: + return "(RF max power reduction)"; + case 0x1F: + return "Measured RX_SENS"; + case 0x20: + return "Extended cell radius"; + case 0x21: + return "reserved"; + case 0x22: + return "Success-Failure"; + case 0x23: + return "Ack-Nack"; + case 0x24: + return "OMU test results"; + case 0x25: + return "File identity"; + case 0x26: + return "Generation and version code"; + case 0x27: + return "SW description"; + case 0x28: + return "BCCH LEV"; + case 0x29: + return "Test type"; + case 0x2A: + return "Subscriber number"; + case 0x2B: + return "reserved"; + case 0x2C: + return "HSN"; + case 0x2D: + return "reserved"; + case 0x2E: + return "MS RXLEV"; + case 0x2F: + return "MS TXLEV"; + case 0x30: + return "RXQUAL"; + case 0x31: + return "RX SENS"; + case 0x32: + return "Alarm block"; + case 0x33: + return "Neighbouring BCCH levels"; + case 0x34: + return "STM report type"; + case 0x35: + return "MA"; + case 0x36: + return "MAIO"; + case 0x37: + return "H_FLAG"; + case 0x38: + return "TCH_ARFN"; + case 0x39: + return "Clock output"; + case 0x3A: + return "Transmitted power"; + case 0x3B: + return "Clock sync"; + case 0x3C: + return "TMS protocol discriminator"; + case 0x3D: + return "TMS protocol data"; + case 0x3E: + return "FER"; + case 0x3F: + return "SWR result"; + case 0x40: + return "Object identity"; + case 0x41: + return "STM RX Antenna Test"; + case 0x42: + return "reserved"; + case 0x43: + return "reserved"; + case 0x44: + return "Object current state"; + case 0x45: + return "reserved"; + case 0x46: + return "FU channel configuration"; + case 0x47: + return "reserved"; + case 0x48: + return "ARFN of a CU"; + case 0x49: + return "FU radio definition"; + case 0x4A: + return "reserved"; + case 0x4B: + return "Severity"; + case 0x4C: + return "Diversity selection"; + case 0x4D: + return "RX antenna test"; + case 0x4E: + return "RX antenna supervision period"; + case 0x4F: + return "RX antenna state"; + case 0x50: + return "Sector configuration"; + case 0x51: + return "Additional info"; + case 0x52: + return "SWR parameters"; + case 0x53: + return "HW inquiry mode"; + case 0x54: + return "reserved"; + case 0x55: + return "Availability status"; + case 0x56: + return "reserved"; + case 0x57: + return "EAC inputs"; + case 0x58: + return "EAC outputs"; + case 0x59: + return "reserved"; + case 0x5A: + return "Position"; + case 0x5B: + return "HW unit identity"; + case 0x5C: + return "RF test signal attenuation"; + case 0x5D: + return "Operational state"; + case 0x5E: + return "Logical object identity"; + case 0x5F: + return "reserved"; + case 0x60: + return "BS_TXPWR_OM"; + case 0x61: + return "Loop_Duration"; + case 0x62: + return "LNA_Path_Selection"; + case 0x63: + return "Serial number"; + case 0x64: + return "HW version"; + case 0x65: + return "Obj. identity and obj. state"; + case 0x66: + return "reserved"; + case 0x67: + return "EAC input definition"; + case 0x68: + return "EAC id and text"; + case 0x69: + return "HW unit status"; + case 0x6A: + return "SW release version"; + case 0x6B: + return "FW version"; + case 0x6C: + return "Bit_Error_Ratio"; + case 0x6D: + return "RXLEV_with_Attenuation"; + case 0x6E: + return "RXLEV_without_Attenuation"; + case 0x6F: + return "reserved"; + case 0x70: + return "CU_Results"; + case 0x71: + return "reserved"; + case 0x72: + return "LNA_Path_Results"; + case 0x73: + return "RTE Results"; + case 0x74: + return "Real Time"; + case 0x75: + return "RX diversity selection"; + case 0x76: + return "EAC input config"; + case 0x77: + return "Feature support"; + case 0x78: + return "File version"; + case 0x79: + return "Outputs"; + case 0x7A: + return "FU parameters"; + case 0x7B: + return "Diagnostic info"; + case 0x7C: + return "FU BSIC"; + case 0x7D: + return "TRX Configuration"; + case 0x7E: + return "Download status"; + case 0x7F: + return "RX difference limit"; + case 0x80: + return "TRX HW capability"; + case 0x81: + return "Common HW config"; + case 0x82: + return "Autoconfiguration pool size"; + case 0x83: + return "TRE diagnostic info"; + case 0x84: + return "TRE object identity"; + case 0x85: + return "New TRE Info"; + case 0x86: + return "Acknowledgement period"; + case 0x87: + return "Synchronization mode"; + case 0x88: + return "reserved"; + case 0x89: + return "Block Control Data"; + case 0x8A: + return "SW load mode"; + case 0x8B: + return "Recommended recovery action"; + case 0x8C: + return "BSC BCF id"; + case 0x8D: + return "Q1 baud rate"; + case 0x8E: + return "Allocation status"; + case 0x8F: + return "Functional entity number"; + case 0x90: + return "Transmission delay"; + case 0x91: + return "Loop Duration ms"; + case 0x92: + return "Logical channel"; + case 0x93: + return "Q1 address"; + case 0x94: + return "Alarm detail"; + case 0x95: + return "Cabinet type"; + case 0x96: + return "HW unit existence"; + case 0x97: + return "RF power parameters"; + case 0x98: + return "Message scenario"; + case 0x99: + return "HW unit max amount"; + case 0x9A: + return "Master TRX"; + case 0x9B: + return "Transparent data"; + case 0x9C: + return "BSC topology info"; + case 0x9D: + return "Air i/f modulation"; + case 0x9E: + return "LCS Q1 command data"; + case 0x9F: + return "Frame number offset"; + case 0xA0: + return "Abis TSL"; + case 0xA1: + return "Dynamic pool info"; + case 0xA2: + return "LCS LLP data"; + case 0xA3: + return "LCS Q1 answer data"; + case 0xA4: + return "DFCA FU Radio Definition"; + case 0xA5: + return "Antenna hopping"; + case 0xA6: + return "Field record sequence number"; + case 0xA7: + return "Timeslot offslot"; + case 0xA8: + return "EPCR capability"; + case 0xA9: + return "Connectsite optional element"; + case 0xAA: + return "TSC"; + case 0xAB: + return "Special TX Power Setting"; + case 0xAC: + return "Optional sync settings"; + case 0xFA: + return "Abis If parameters"; + default: + return "unknown"; + } +} + +static char *get_bts_type_string(uint8_t type) +{ + switch(type) { + case 0x0A: + return "MetroSite GSM 900"; + case 0x0B: + return "MetroSite GSM 1800"; + case 0x0C: + return "MetroSite GSM 1900 (PCS)"; + case 0x0D: + return "MetroSite GSM 900 & 1800"; + case 0x0E: + return "InSite GSM 900"; + case 0x0F: + return "InSite GSM 1800"; + case 0x10: + return "InSite GSM 1900"; + case 0x11: + return "UltraSite GSM 900"; + case 0x12: + return "UltraSite GSM 1800"; + case 0x13: + return "UltraSite GSM/US-TDMA 1900"; + case 0x14: + return "UltraSite GSM 900 & 1800"; + case 0x16: + return "UltraSite GSM/US-TDMA 850"; + case 0x18: + return "MetroSite GSM/US-TDMA 850"; + case 0x19: + return "UltraSite GSM 800/1900"; + default: + return "unknown"; + } +} + +static char *get_severity_string(uint8_t severity) +{ + switch(severity) { + case 0: + return "indeterminate"; + case 1: + return "critical"; + case 2: + return "major"; + case 3: + return "minor"; + case 4: + return "warning"; + default: + return "unknown"; + } +} + +/* TODO: put in a separate file ? */ + +/* some message IDs */ + +#define NOKIA_MSG_CONF_DATA 128 +#define NOKIA_MSG_ACK 129 +#define NOKIA_MSG_OMU_STARTED 130 +#define NOKIA_MSG_START_DOWNLOAD_REQ 131 +#define NOKIA_MSG_MF_REQ 132 +#define NOKIA_MSG_RESET_REQ 134 +#define NOKIA_MSG_CONF_REQ 136 +#define NOKIA_MSG_CONF_COMPLETE 142 +#define NOKIA_MSG_BLOCK_CTRL_REQ 168 +#define NOKIA_MSG_STATE_CHANGED 172 +#define NOKIA_MSG_ALARM 174 + +/* some element IDs */ + +#define NOKIA_EI_BTS_TYPE 0x13 +#define NOKIA_EI_ACK 0x23 +#define NOKIA_EI_ADD_INFO 0x51 +#define NOKIA_EI_SEVERITY 0x4B +#define NOKIA_EI_ALARM_DETAIL 0x94 + +#define OM_ALLOC_SIZE 1024 +#define OM_HEADROOM_SIZE 128 + +static uint8_t fu_config_template[] = +{ + 0x7F, 0x7A, 0x39, + /* ID = 0x7A (FU parameters) ## constructed ## */ + /* length = 57 */ + /* [3] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [6] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x41, 0x02, + /* ID = 0x01 (Ny1) */ + /* length = 2 */ + /* [12] */ + 0x00, 0x05, + + 0x42, 0x02, + /* ID = 0x02 (T3105_F) */ + /* length = 2 */ + /* [16] */ + 0x00, 0x28, + + 0x50, 0x02, + /* ID = 0x10 (T3105_D) */ + /* length = 2 */ + /* [20] */ + 0x00, 0x28, + + 0x43, 0x05, + /* ID = 0x03 (Interference band limits) */ + /* length = 5 */ + /* [24] */ + 0x0F, 0x1B, 0x27, 0x33, 0x3F, + + 0x44, 0x02, + /* ID = 0x04 (Interference report timer in secs) */ + /* length = 2 */ + /* [31] */ + 0x00, 0x10, + + 0x47, 0x01, + /* ID = 0x07 (RACH report timer in secs) */ + /* length = 1 */ + /* [35] */ + 0x1E, + + 0x4C, 0x10, + /* ID = 0x0C (Cell allocation bitmap) ####### */ + /* length = 16 */ + /* [38] */ + 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x59, 0x01, + /* ID = 0x19 (Averaging period) */ + /* length = 1 */ + /* [56] */ + 0x01, + + 0x5E, 0x01, + /* ID = 0x1E ((RF max power reduction)) */ + /* length = 1 */ + /* [59] */ + 0x00, + + + 0x7F, 0x46, 0x11, + /* ID = 0x46 (FU channel configuration) ## constructed ## */ + /* length = 17 */ + /* [63] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [66] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x45, 0x08, + /* ID = 0x05 (Channel configuration per TS) */ + /* length = 8 */ + /* [72] */ + 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + + + 0x7F, 0x65, 0x0B, + /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */ + /* length = 11 */ + /* [83] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [86] */ + 0x00, 0x04, 0x01, 0xFF, + + 0x5F, 0x44, 0x01, + /* ID = 0x44 (Object current state) */ + /* length = 1 */ + /* [93] */ + 0x03, + + + 0x7F, 0x7C, 0x0A, + /* ID = 0x7C (FU BSIC) ## constructed ## */ + /* length = 10 */ + /* [97] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [100] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x46, 0x01, + /* ID = 0x06 (BSIC) */ + /* length = 1 */ + /* [106] */ + 0x00, + + + 0x7F, 0x48, 0x0B, + /* ID = 0x48 (ARFN of a CU) ## constructed ## */ + /* length = 11 */ + /* [110] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [113] */ + 0x00, 0x08, 0x01, 0xFF, + + 0x4A, 0x02, + /* ID = 0x0A (ARFN) ####### */ + /* length = 2 */ + /* [119] */ + 0x03, 0x62, + + + 0x7F, 0x49, 0x59, + /* ID = 0x49 (FU radio definition) ## constructed ## */ + /* length = 89 */ + /* [124] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [127] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x4D, 0x50, + /* ID = 0x0D (Radio definition per TS) ####### */ + /* length = 80 */ + /* [133] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */ + 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, +}; + +/* TODO: put in a separate file ? */ + +/* + build the configuration for each TRX +*/ + +static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, uint8_t *fu_config, int *hopping) +{ + int i; + + *hopping = 0; + + memcpy(fu_config, fu_config_template, sizeof(fu_config_template)); + + /* set ID */ + + fu_config[ 6 + 2] = id; + fu_config[ 66 + 2] = id; + fu_config[ 86 + 2] = id; + fu_config[100 + 2] = id; + fu_config[113 + 2] = id; + fu_config[127 + 2] = id; + + /* set ARFCN */ + + uint16_t arfcn = trx->arfcn; + + fu_config[119] = arfcn >> 8; + fu_config[119 + 1] = arfcn & 0xFF; + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + + if (ts->hopping.enabled) { + /* reverse order */ + int j; + for(j = 0; j < ts->hopping.ma_len; j++) + fu_config[133 + (i * 10) + (7 - j)] = ts->hopping.ma_data[j]; + fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn; + fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio; + *hopping = 1; + } else { + fu_config[133 + 8 + (i * 10)] = arfcn >> 8; + fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF; + } + } + + /* set BSIC */ + + /* + Attention: all TRX except the first one seem to get the TSC + from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION, + GSM 04.08 CHANNEL DESCRIPTION). + There was a bug in rsl_chan_activate_lchan() setting this parameter. + */ + + uint8_t bsic = trx->bts->bsic; + + fu_config[106] = bsic; + + /* set CA */ + + if(generate_cell_chan_list(&fu_config[38], trx->bts) != 0) { + fprintf(stderr, "generate_cell_chan_list failed\n"); + return 0; + } + + /* set channel configuration */ + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + uint8_t chan_config; + + /* + 0 = FCCH + SCH + BCCH + CCCH + 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4 + 2 = BCCH + CCCH (This combination is not used in any BTS) + 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH + 4 = SDCCH/8 + SACCH/8 + 5 = SDCCH/8 with SDCCH2 used as CBCH + 6 = TCH/F + FACCH/F + SACCH/F + 7 = E-RACH (Talk family) + 9 = Dual rate (capability for TCH/F and TCH/H) + 10 = reserved for BTS internal use + 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (This channel configuration type can be used in GPRS release 2). + 0xFF = spare TS + */ + + if(ts->pchan == GSM_PCHAN_NONE) + chan_config = 0xFF; + else if(ts->pchan == GSM_PCHAN_CCCH) + chan_config = 0; + else if(ts->pchan == GSM_PCHAN_CCCH_SDCCH4) + chan_config = 1; + else if(ts->pchan == GSM_PCHAN_TCH_F) + chan_config = 6; /* 9 should work too */ + else if(ts->pchan == GSM_PCHAN_TCH_H) + chan_config = 9; + else if(ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C) + chan_config = 4; + else if(ts->pchan == GSM_PCHAN_PDCH) + chan_config = 11; + else { + fprintf(stderr, "unsupported channel config %d for timeslot %d\n", ts->pchan, i); + return 0; + } + + fu_config[72 + i] = chan_config; + } + return sizeof(fu_config_template); +} + +/* TODO: put in a separate file ? */ + +static uint8_t bts_config_1[] = +{ + 0x4E, 0x02, + /* ID = 0x0E (Frame number) */ + /* length = 2 */ + /* [2] */ + 0xFF, 0xFF, + + 0x5F, 0x4E, 0x02, + /* ID = 0x4E (RX antenna supervision period) */ + /* length = 2 */ + /* [7] */ + 0xFF, 0xFF, + + 0x5F, 0x50, 0x02, + /* ID = 0x50 (Sector configuration) */ + /* length = 2 */ + /* [12] */ + 0x01, 0x01, +}; + +static uint8_t bts_config_2[] = +{ + 0x55, 0x02, + /* ID = 0x15 (Hopping mode) */ + /* length = 2 */ + /* [2] */ + 0x01, 0x00, + + 0x5F, 0x75, 0x02, + /* ID = 0x75 (RX diversity selection) */ + /* length = 2 */ + /* [7] */ + 0x01, 0x01, +}; + +static uint8_t bts_config_3[] = +{ + 0x5F, 0x20, 0x02, + /* ID = 0x20 (Extended cell radius) */ + /* length = 2 */ + /* [3] */ + 0x01, 0x00, +}; + +static uint8_t bts_config_4[] = +{ + 0x5F, 0x74, 0x09, + /* ID = 0x74 (Real Time) */ + /* length = 9 */ + /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ + 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00, + 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [15] */ + 0x01, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [21] */ + 0x02, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [27] */ + 0x03, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [33] */ + 0x04, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [39] */ + 0x05, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [45] */ + 0x06, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [51] */ + 0x07, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [57] */ + 0x08, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [63] */ + 0x09, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [69] */ + 0x0A, 0x01, 0x00, +}; + +static uint8_t bts_config_insite[] = +{ + 0x4E, 0x02, + /* ID = 0x0E (Frame number) */ + /* length = 2 */ + /* [2] */ + 0xFF, 0xFF, + + 0x5F, 0x4E, 0x02, + /* ID = 0x4E (RX antenna supervision period) */ + /* length = 2 */ + /* [7] */ + 0xFF, 0xFF, + + 0x5F, 0x50, 0x02, + /* ID = 0x50 (Sector configuration) */ + /* length = 2 */ + /* [12] */ + 0x01, 0x01, + + 0x55, 0x02, + /* ID = 0x15 (Hopping mode) */ + /* length = 2 */ + /* [16] */ + 0x01, 0x00, + + 0x5F, 0x20, 0x02, + /* ID = 0x20 (Extended cell radius) */ + /* length = 2 */ + /* [21] */ + 0x01, 0x00, + + 0x5F, 0x74, 0x09, + /* ID = 0x74 (Real Time) */ + /* length = 9 */ + /* [26] */ + 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00, + 0x00, +}; + +void set_real_time(uint8_t *real_time) +{ + time_t t; + struct tm *tm; + + t = time(NULL); + tm = localtime(&t); + + /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ + + real_time[0] = (1900 + tm->tm_year) >> 8; + real_time[1] = (1900 + tm->tm_year) & 0xFF; + real_time[2] = tm->tm_mon + 1; + real_time[3] = tm->tm_mday; + real_time[4] = tm->tm_hour; + real_time[5] = tm->tm_min; + real_time[6] = tm->tm_sec; + real_time[7] = 0; + real_time[8] = 0; +} + +/* TODO: put in a separate file ? */ + +/* + + build the configuration data + +*/ + +static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t *fu_config, int need_hopping) +{ + /* is it an InSite BTS ? */ + if(bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */ + if(n_trx != 1) { + fprintf(stderr, "InSite has only one TRX\n"); + return 0; + } + if(need_hopping != 0) { + fprintf(stderr, "InSite does not support hopping\n"); + return 0; + } + memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite)); + set_real_time(&fu_config[26]); + return sizeof(bts_config_insite); + } + + int len = 0; + int i; + + memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1)); + + /* set sector configuration */ + fu_config[len + 12 - 1] = 1 + n_trx; /* len */ + for(i = 0; i < n_trx; i++) + fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF); + + len += (sizeof(bts_config_1) + (n_trx - 1)); + + memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2)); + /* set hopping mode (Baseband and RF hopping work for the MetroSite) */ + if(need_hopping) + fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */ + len += sizeof(bts_config_2); + + /* set extended cell radius for each TRX */ + for(i = 0; i < n_trx; i++) { + memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3)); + fu_config[len + 3] = ((i + 1) & 0xFF); + len += sizeof(bts_config_3); + } + + memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4)); + set_real_time(&fu_config[len + 3]); + len += sizeof(bts_config_4); + + return len; +} + +/* TODO: put in a separate file ? */ + +static struct msgb *nm_msgb_alloc(void) +{ + return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, + "OML"); +} + +/* TODO: put in a separate file ? */ + +struct abis_om_nokia_hdr { + uint8_t msg_type; + uint8_t spare; + uint16_t reference; + uint8_t data[0]; +} __attribute__ ((packed)); + +#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr)) + +static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref, uint8_t *data, int len_data) +{ + struct abis_om_hdr *oh; + struct abis_om_nokia_hdr *noh; + struct msgb *msg = nm_msgb_alloc(); + + oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_NOKIA_HDR_SIZE + len_data); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_ONLY; + oh->sequence = 0; + oh->length = sizeof(struct abis_om_nokia_hdr) + len_data; + + noh = (struct abis_om_nokia_hdr *)oh->data; + + noh->msg_type = msg_type; + noh->spare = 0; + noh->reference = htons(ref); + memcpy(noh->data, data, len_data); + + DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type)); + + return abis_nm_sendmsg(bts, msg); +} + +/* TODO: put in a separate file ? */ + +static uint8_t download_req[] = { + 0x5F, 0x25, 0x0B, + /* ID = 0x25 (File identity) */ + /* length = 11 */ + /* [3] */ + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x2A, 0x2A, 0x2A, + + 0x5F, 0x78, 0x03, + /* ID = 0x78 (File version) */ + /* length = 3 */ + /* [17] */ + 0x2A, 0x2A, 0x2A, + + 0x5F, 0x81, 0x0A, 0x01, + /* ID = 0x8A (SW load mode) */ + /* length = 1 */ + /* [24] */ + 0x01, + + 0x5F, 0x81, 0x06, 0x01, + /* ID = 0x86 (Acknowledgement period) */ + /* length = 1 */ + /* [29] */ + 0x01, +}; + +static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref) +{ + uint8_t *data = download_req; + int len_data = sizeof(download_req); + + return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data, len_data); +} + +/* TODO: put in a separate file ? */ + +static uint8_t ack[] = { + 0x5F, 0x23, 0x01, + /* ID = 0x23 (Ack-Nack) */ + /* length = 1 */ + /* [3] */ + 0x01, +}; + +static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref) +{ + uint8_t *data = ack; + int len_data = sizeof(ack); + + return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data); +} + +/* TODO: put in a separate file ? */ + +static uint8_t reset[] = { + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [3] */ + 0x00, 0x01, 0xFF, 0xFF, +}; + +static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref) +{ + uint8_t *data = reset; + int len_data = sizeof(reset); + + return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data); +} + +/* TODO: put in a separate file ? */ + +static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref, uint8_t *data, int len) +{ + int len_remain, len_to_send, max_send; + int seq = 0; + int ret; + + len_remain = len; + + while(len_remain) { + struct abis_om_hdr *oh; + struct abis_om_nokia_hdr *noh; + struct msgb *msg = nm_msgb_alloc(); + + if(seq == 0) + max_send = 256 - sizeof(struct abis_om_nokia_hdr); + else + max_send = 256; + + if(len_remain > max_send) { + len_to_send = max_send; + + if(seq == 0) { + /* first segment */ + oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_NOKIA_HDR_SIZE + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */ + oh->sequence = seq; + oh->length = 0; /* 256 bytes */ + + noh = (struct abis_om_nokia_hdr *)oh->data; + + noh->msg_type = msg_type; + noh->spare = 0; + noh->reference = htons(ref); + memcpy(noh->data, data, len_to_send); + } else { + /* segment in between */ + oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(struct abis_om_hdr) + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */ + oh->sequence = seq; + oh->length = 0; /* 256 bytes */ + + memcpy(oh->data, data, len_to_send); + } + } + else { + + len_to_send = len_remain; + + /* check if message fits in a single segment */ + + if(seq == 0) + return abis_nm_send(bts, msg_type, ref, data, len_to_send); + + /* last segment */ + + oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(struct abis_om_hdr) + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */ + oh->sequence = seq; + oh->length = len_to_send; + + memcpy(oh->data, data, len_to_send); + } + + DEBUGPC(DNM, "Sending multi-segment %d\n", seq); + + ret = abis_nm_sendmsg(bts, msg); + if(ret < 0) + return ret; + + abis_nm_queue_send_next(bts); + + /* next segment */ + len_remain -= len_to_send; + data += len_to_send; + seq++; + } + return ret; +} + +/* TODO: put in a separate file ? */ + +static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type) +{ + struct gsm_bts_trx *trx; + uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */ + int len = 0; + int idx = 0; + int ret; + int hopping = 0; + int need_hopping = 0; + + memset(config, 0, sizeof(config)); + + llist_for_each_entry(trx, &bts->trx_list, list) + { +#if 0 /* debugging */ + printf("TRX\n"); + printf(" arfcn: %d\n", trx->arfcn); + printf(" bsic: %d\n", trx->bts->bsic); + uint8_t ca[20]; + memset(ca, 0xFF, sizeof(ca)); + ret = generate_cell_chan_list(ca, trx->bts); + printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca))); + int i; + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + + printf(" pchan %d: %d\n", i, ts->pchan); + } +#endif + ret = make_fu_config(trx, idx + 1, config + len, &hopping); + need_hopping |= hopping; + len += ret; + + idx++; + } + + ret = make_bts_config(bts_type, idx, config + len, need_hopping); + len += ret; + +#if 0 /* debugging */ + dump_elements(config, len); +#endif + + return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config, len); +} + +#define GET_NEXT_BYTE if(idx >= len) return 0; \ + ub = data[idx++]; + +static int find_element(uint8_t *data, int len, uint16_t id, uint8_t *value, int max_value) +{ + uint8_t ub; + int idx = 0; + int found = 0; + int constructed; + uint16_t id_value; + + for(;;) { + + GET_NEXT_BYTE; + + /* encoding bit, construced means that other elements are contained */ + constructed = ((ub & 0x20) ? 1 : 0); + + if((ub & 0x1F) == 0x1F) { + /* fixed pattern, ID follows */ + GET_NEXT_BYTE; /* ID */ + id_value = ub & 0x7F; + if(ub & 0x80) { + /* extension bit */ + GET_NEXT_BYTE; /* ID low part */ + id_value = (id_value << 7) | (ub & 0x7F); + } + if(id_value == id) + found = 1; + } + else { + id_value = (ub & 0x3F); + if(id_value == id) + found = 1; + } + + GET_NEXT_BYTE; /* length */ + + if(found) { + /* get data */ + uint8_t n = ub; + uint8_t i; + for(i = 0; i < n; i++) { + GET_NEXT_BYTE; + if(max_value <= 0) + return -1; /* buffer too small */ + *value = ub; + value++; + max_value--; + } + return n; /* length */ + } + else { + /* skip data */ + uint8_t n = ub; + uint8_t i; + for(i = 0; i < n; i++) { + GET_NEXT_BYTE; + } + } + } + return 0; /* not found */ +} + +static int dump_elements(uint8_t *data, int len) +{ + uint8_t ub; + int idx = 0; + int constructed; + uint16_t id_value; + static char indent[100] = ""; /* TODO: move static to BTS context */ + + for(;;) { + + GET_NEXT_BYTE; + + /* encoding bit, construced means that other elements are contained */ + constructed = ((ub & 0x20) ? 1 : 0); + + if((ub & 0x1F) == 0x1F) { + /* fixed pattern, ID follows */ + GET_NEXT_BYTE; /* ID */ + id_value = ub & 0x7F; + if(ub & 0x80) { + /* extension bit */ + GET_NEXT_BYTE; /* ID low part */ + id_value = (id_value << 7) | (ub & 0x7F); + } + + } + else { + id_value = (ub & 0x3F); + } + + GET_NEXT_BYTE; /* length */ + + printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value, get_element_name_string(id_value), constructed ? "** constructed **" : ""); + printf("%s length = %d\n", indent, ub); + printf("%s %s\n", indent, osmo_hexdump(data + idx, ub)); + + if(constructed) { + int indent_len = strlen(indent); + strcat(indent, " "); + + dump_elements(data + idx, ub); + + indent[indent_len] = 0; + } + /* skip data */ + uint8_t n = ub; + uint8_t i; + for(i = 0; i < n; i++) { + GET_NEXT_BYTE; + } + } + return 0; +} + +/* TODO: put in a separate file ? */ + +/* taken from abis_nm.c */ + +static void abis_nm_queue_send_next(struct gsm_bts *bts) +{ + int wait = 0; + struct msgb *msg; + /* the queue is empty */ + while (!llist_empty(&bts->abis_queue)) { + msg = msgb_dequeue(&bts->abis_queue); + wait = OBSC_NM_W_ACK_CB(msg); + _abis_nm_sendmsg(msg, 0); + + if (wait) + break; + } + + bts->abis_nm_pend = wait; +} + +/* TODO: put in a separate file ? */ + +/* timer for restarting OML after BTS reset */ + +static void reset_timer_cb(void *_bts) +{ + struct gsm_bts *bts = _bts; + struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; + struct e1inp_line *line; + + wait_reset = 0; + + /* OML link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to " + "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); + return; + } + + start_sabm_in_line(line, 0, -1); /* stop all first */ + start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */ +} + +/* TODO: put in a separate file ? */ + +/* + This is how the configuration is done: + + - start OML link + + - reset BTS + + - receive ACK, wait some time and restart OML link + + - receive OMU STARTED message, send START DOWNLOAD REQ + + - receive CNF REQ message, send CONF DATA + + - receive ACK, start RSL link(s) + + ACK some other messages received from the BTS. + + Probably its also possible to configure the BTS without a reset, this + has not been tested yet. +*/ + +static int abis_nm_rcvmsg_fom(struct msgb *mb) +{ + struct gsm_bts *bts = mb->trx->bts; + struct abis_om_hdr *oh = msgb_l2(mb); + struct abis_om_nokia_hdr *noh = msgb_l3(mb); + uint8_t mt = noh->msg_type; + int ret = 0; + uint16_t ref = ntohs(noh->reference); + /* TODO: move statics to BTS context */ + static int conf = 0; + static uint8_t bts_type = 0xFF; + uint8_t info[256]; + uint8_t ack = 0xFF; + uint8_t severity = 0xFF; + int str_len; + int len_data; + + if(wait_reset) { + LOGP(DNM, LOGL_INFO, "Ignore message while waiting for reset\n"); + return ret; + } + + if(oh->length < sizeof(struct abis_om_nokia_hdr)) { + LOGP(DNM, LOGL_ERROR, "Message too short\n"); + return -EINVAL; + } + + len_data = oh->length - sizeof(struct abis_om_nokia_hdr); + LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt)); +#if 0 /* debugging */ + dump_elements(noh->data, len_data); +#endif + + switch (mt) { + case NOKIA_MSG_OMU_STARTED: + if(find_element(noh->data, len_data, NOKIA_EI_BTS_TYPE, &bts_type, sizeof(uint8_t)) == sizeof(uint8_t)) + LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", bts_type, get_bts_type_string(bts_type)); + else + LOGP(DNM, LOGL_ERROR, "BTS type not found\n"); + /* send START_DOWNLOAD_REQ */ + abis_nm_download_req(bts, ref); + break; + case NOKIA_MSG_MF_REQ: + break; + case NOKIA_MSG_CONF_REQ: + /* send ACK */ + abis_nm_ack(bts, ref); + abis_nm_queue_send_next(bts); + /* send CONF_DATA */ + abis_nm_send_config(bts, bts_type); + conf = 1; + break; + case NOKIA_MSG_ACK: + if(find_element(noh->data, len_data, NOKIA_EI_ACK, &ack, sizeof(uint8_t)) == sizeof(uint8_t)) { + LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack); + if(ack != 1) { + LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n", ack); + /* TODO: properly handle failures (NACK) */ + } + } + else + LOGP(DNM, LOGL_ERROR, "ACK not found\n"); + + /* TODO: the assumption for the following is that no NACK was received */ + + /* ACK for reset message ? */ + if(do_reset != 0) { + do_reset = 0; + + /* + TODO: For the InSite processing the received data is + blocked in the driver during reset. + Otherwise the LAPD module might assert because the InSite + sends garbage on the E1 line during reset. + This is done by looking at "wait_reset" in the driver + (function handle_ts1_read()) and ignoring the received data. + It seems to be necessary for the MetroSite too. + */ + wait_reset = 1; + + reset_timer.cb = &reset_timer_cb; + reset_timer.data = bts; + osmo_timer_schedule(&reset_timer, RESET_INTERVAL); + + struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; + struct e1inp_line *line; + /* OML link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to " + "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); + return -ENOMEM; + } + + start_sabm_in_line(line, 0, -1); /* stop all first */ + } + + /* ACK for CONF DATA message ? */ + if(conf != 0) { + /* start TRX (RSL link) */ + + struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link; + struct e1inp_line *line; + + conf = 0; + + /* RSL Link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring " + "to non-existing E1 line %u\n", mb->trx->bts->nr, + mb->trx->nr, e1_link->e1_nr); + return -ENOMEM; + } + /* start TRX */ + start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */ + } + break; + case NOKIA_MSG_STATE_CHANGED: + /* send ACK */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_CONF_COMPLETE: + /* send ACK */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */ + /* send ACK (do we have to send an ACK ?) */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_ALARM: + find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity, sizeof(severity)); + /* TODO: there might be alarms with both elements set */ + str_len = find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info, sizeof(info)); + if(str_len > 0) { + info[str_len] = 0; + LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n", get_severity_string(severity), severity, info); + } else { /* nothing found, try details */ + str_len = find_element(noh->data, len_data, NOKIA_EI_ALARM_DETAIL, info, sizeof(info)); + if(str_len > 0) { + uint16_t code; + info[str_len] = 0; + code = (info[0] << 8) + info[1]; + LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d), code 0x%X : %s\n", get_severity_string(severity), severity, code, info + 2); + } + } + /* send ACK */ + abis_nm_ack(bts, ref); + break; + } + + abis_nm_queue_send_next(bts); + + return ret; +} + +/* TODO: put in a separate file ? */ + +int abis_nokia_rcvmsg(struct msgb *msg) +{ + struct abis_om_hdr *oh = msgb_l2(msg); + int rc = 0; + + /* Various consistency checks */ + if (oh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n", + oh->placement); + if (oh->placement != ABIS_OM_PLACEMENT_FIRST) + return -EINVAL; + } + if (oh->sequence != 0) { + LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n", + oh->sequence); + return -EINVAL; + } + msg->l3h = (unsigned char *)oh + sizeof(*oh); + + switch (oh->mdisc) { + case ABIS_OM_MDISC_FOM: + LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n"); + rc = abis_nm_rcvmsg_fom(msg); + break; + case ABIS_OM_MDISC_MANUF: + LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n"); + break; + case ABIS_OM_MDISC_MMI: + case ABIS_OM_MDISC_TRAU: + LOGP(DNM, LOGL_ERROR, "unimplemented ABIS OML message discriminator 0x%x\n", + oh->mdisc); + break; + default: + LOGP(DNM, LOGL_ERROR, "unknown ABIS OML message discriminator 0x%x\n", + oh->mdisc); + return -EINVAL; + } + + msgb_free(msg); + return rc; +} + +static int bts_model_nokia_site_start(struct gsm_network *net); + +static struct gsm_bts_model model_nokia_site = { + .type = GSM_BTS_TYPE_NOKIA_SITE, + .name = "nokia_site", + .start = bts_model_nokia_site_start, + .oml_rcvmsg = &abis_nokia_rcvmsg +}; + +static struct gsm_network *my_net; + +static int bts_model_nokia_site_start(struct gsm_network *net) +{ + model_nokia_site.features.data = &model_nokia_site._features_data[0]; + model_nokia_site.features.data_len = sizeof(model_nokia_site._features_data); + + gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING); + gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD); + + osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL); + osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL); + osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); + + my_net = net; + + return 0; +} + +int bts_model_nokia_site_init(void) +{ + return gsm_bts_model_register(&model_nokia_site); +} + diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 353b3dd9b..5814c765c 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -154,7 +154,7 @@ static int bitvec2freq_list(uint8_t *chan_list, struct bitvec *bv, } /* generate a cell channel list as per Section 10.5.2.1b of 04.08 */ -static int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts) +/* static*/ int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts) { struct gsm_bts_trx *trx; struct bitvec *bv = &bts->si_common.cell_alloc; diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c index 6b15bd06c..c70ffaee7 100644 --- a/openbsc/src/libcommon/gsm_data.c +++ b/openbsc/src/libcommon/gsm_data.c @@ -193,6 +193,7 @@ static const struct value_string bts_types[] = { { GSM_BTS_TYPE_NANOBTS, "nanobts" }, { GSM_BTS_TYPE_RBS2000, "rbs2000" }, { GSM_BTS_TYPE_HSL_FEMTO, "hsl_femto" }, + { GSM_BTS_TYPE_NOKIA_SITE, "nokia_site" }, { 0, NULL } }; diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index ff012246d..b0bfecadd 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1634,6 +1634,7 @@ static int tch_map(struct gsm_lchan *lchan, struct gsm_lchan *remote_lchan) break; case GSM_BTS_TYPE_BS11: case GSM_BTS_TYPE_RBS2000: + case GSM_BTS_TYPE_NOKIA_SITE: trau_mux_map_lchan(lchan, remote_lchan); break; default: -- cgit v1.2.3 From bda367c697a639707a136528f1e93b365d3611fb Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:03:49 +0200 Subject: Nokia: Coding style Running the entire bts_nokia_site.c through the 'Lindent' script to match indent/coding style with remainder of project. There are still lots of other cleanups pending, but this one is a purely cosmetic one. --- openbsc/src/libbsc/bts_nokia_site.c | 3299 ++++++++++++++++++----------------- 1 file changed, 1666 insertions(+), 1633 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index d30881bba..033f6fec7 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -45,37 +45,37 @@ /* TODO: move statics to BTS context */ static int do_reset = 1; /*static*/ int wait_reset = 0; -struct osmo_timer_list reset_timer; /* timer to re-start after reset */ +struct osmo_timer_list reset_timer; /* timer to re-start after reset */ -#define RESET_INTERVAL 0, 3000000 /* 3 seconds */ +#define RESET_INTERVAL 0, 3000000 /* 3 seconds */ extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg); /* was static in system_information.c */ -extern int generate_cell_chan_list(uint8_t *chan_list, struct gsm_bts *bts); +extern int generate_cell_chan_list(uint8_t * chan_list, struct gsm_bts *bts); static void abis_nm_queue_send_next(struct gsm_bts *bts); static void reset_timer_cb(void *_bts); static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref); -static int dump_elements(uint8_t *data, int len); +static int dump_elements(uint8_t * data, int len); static void bootstrap_om_bts(struct gsm_bts *bts) { - LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); - - if(do_reset) - abis_nm_reset(bts, 1); + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); + + if (do_reset) + abis_nm_reset(bts, 1); } static void bootstrap_om_trx(struct gsm_bts_trx *trx) { - LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n", - trx->bts->nr, trx->nr); + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n", + trx->bts->nr, trx->nr); } static int shutdown_om(struct gsm_bts *bts) { - /* TODO !? */ - return 0; + /* TODO !? */ + return 0; } #define SAPI_OML 62 @@ -88,644 +88,647 @@ static int shutdown_om(struct gsm_bts *bts) Attention: this has to be adapted for MISDN */ - + static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) { - struct e1inp_sign_link *link; - int i; + struct e1inp_sign_link *link; + int i; - for (i = 0; i < ARRAY_SIZE(line->ts); i++) { - struct e1inp_ts *ts = &line->ts[i]; + for (i = 0; i < ARRAY_SIZE(line->ts); i++) { + struct e1inp_ts *ts = &line->ts[i]; - if (ts->type != E1INP_TS_TYPE_SIGN) - continue; + if (ts->type != E1INP_TS_TYPE_SIGN) + continue; - llist_for_each_entry(link, &ts->sign.sign_links, list) { - if(sapi != -1 && link->sapi != sapi) - continue; - -#if 0 /* debugging */ - printf("sap start/stop (%d): %d tei=%d sapi=%d\n", start, i + 1, link->tei, link->sapi); + llist_for_each_entry(link, &ts->sign.sign_links, list) { + if (sapi != -1 && link->sapi != sapi) + continue; + +#if 0 /* debugging */ + printf("sap start/stop (%d): %d tei=%d sapi=%d\n", + start, i + 1, link->tei, link->sapi); #endif - - if (start) - lapd_sap_start(ts->driver.dahdi.lapd, link->tei, link->sapi); - else - lapd_sap_stop(ts->driver.dahdi.lapd, link->tei, link->sapi); - } - } + + if (start) + lapd_sap_start(ts->driver.dahdi.lapd, link->tei, + link->sapi); + else + lapd_sap_stop(ts->driver.dahdi.lapd, link->tei, + link->sapi); + } + } } /* Callback function to be called every time we receive a signal from INPUT */ static int gbl_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) + void *handler_data, void *signal_data) { - struct gsm_bts *bts; + struct gsm_bts *bts; - if (subsys != SS_GLOBAL) - return 0; + if (subsys != SS_GLOBAL) + return 0; - switch (signal) { - case S_GLOBAL_BTS_CLOSE_OM: - bts = signal_data; - if (bts->type == GSM_BTS_TYPE_NOKIA_SITE) - shutdown_om(signal_data); - break; - } + switch (signal) { + case S_GLOBAL_BTS_CLOSE_OM: + bts = signal_data; + if (bts->type == GSM_BTS_TYPE_NOKIA_SITE) + shutdown_om(signal_data); + break; + } - return 0; + return 0; } /* Callback function to be called every time we receive a signal from INPUT */ static int inp_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) + void *handler_data, void *signal_data) { - struct input_signal_data *isd = signal_data; - - if (subsys != SS_INPUT) - return 0; - - switch (signal) { - case S_INP_LINE_INIT: - start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */ - break; - case S_INP_TEI_DN: - break; - case S_INP_TEI_UP: - switch (isd->link_type) { - case E1INP_SIGN_OML: - if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE) - break; - - if (isd->tei == isd->trx->bts->oml_tei) - bootstrap_om_bts(isd->trx->bts); - else - bootstrap_om_trx(isd->trx); - break; - } - break; - } - - return 0; + struct input_signal_data *isd = signal_data; + + if (subsys != SS_INPUT) + return 0; + + switch (signal) { + case S_INP_LINE_INIT: + start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */ + break; + case S_INP_TEI_DN: + break; + case S_INP_TEI_UP: + switch (isd->link_type) { + case E1INP_SIGN_OML: + if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE) + break; + + if (isd->tei == isd->trx->bts->oml_tei) + bootstrap_om_bts(isd->trx->bts); + else + bootstrap_om_trx(isd->trx); + break; + } + break; + } + + return 0; } static void nm_statechg_evt(unsigned int signal, - struct nm_statechg_signal_data *nsd) + struct nm_statechg_signal_data *nsd) { - if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE) - return; + if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE) + return; } static int nm_sig_cb(unsigned int subsys, unsigned int signal, - void *handler_data, void *signal_data) + void *handler_data, void *signal_data) { - if (subsys != SS_NM) - return 0; - - switch (signal) { - case S_NM_STATECHG_OPER: - case S_NM_STATECHG_ADM: - nm_statechg_evt(signal, signal_data); - break; - default: - break; - } - - return 0; + if (subsys != SS_NM) + return 0; + + switch (signal) { + case S_NM_STATECHG_OPER: + case S_NM_STATECHG_ADM: + nm_statechg_evt(signal, signal_data); + break; + default: + break; + } + + return 0; } /* TODO: put in a separate file ? */ static char *get_msg_type_name_string(uint8_t msg_type) { - switch(msg_type) { - case 0x80: - return "NOKIA_BTS_CONF_DATA"; - case 0x81: - return "NOKIA_BTS_ACK"; - case 0x82: - return "NOKIA_BTS_OMU_STARTED"; - case 0x83: - return "NOKIA_BTS_START_DOWNLOAD_REQ"; - case 0x84: - return "NOKIA_BTS_MF_REQ"; - case 0x85: - return "NOKIA_BTS_AF_REQ"; - case 0x86: - return "NOKIA_BTS_RESET_REQ"; - case 0x87: - return "NOKIA_reserved"; - case 0x88: - return "NOKIA_BTS_CONF_REQ"; - case 0x89: - return "NOKIA_BTS_TEST_REQ"; - case 0x8A: - return "NOKIA_BTS_TEST_REPORT"; - case 0x8B: - return "NOKIA_reserved"; - case 0x8C: - return "NOKIA_reserved"; - case 0x8D: - return "NOKIA_reserved"; - case 0x8E: - return "NOKIA_BTS_CONF_COMPL"; - case 0x8F: - return "NOKIA_reserved"; - case 0x90: - return "NOKIA_BTS_STM_TEST_REQ"; - case 0x91: - return "NOKIA_BTS_STM_TEST_REPORT"; - case 0x92: - return "NOKIA_BTS_TRANSMISSION_COMMAND"; - case 0x93: - return "NOKIA_BTS_TRANSMISSION_ANSWER"; - case 0x94: - return "NOKIA_BTS_HW_DB_UPLOAD_REQ"; - case 0x95: - return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ"; - case 0x96: - return "NOKIA_BTS_HW_DB_SAVE_REQ"; - case 0x97: - return "NOKIA_BTS_FLASH_ERASURE_REQ"; - case 0x98: - return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ"; - case 0x99: - return "NOKIA_BTS_PWR_SUPPLY_CONTROL"; - case 0x9A: - return "NOKIA_BTS_ATTRIBUTE_REQ"; - case 0x9B: - return "NOKIA_BTS_ATTRIBUTE_REPORT"; - case 0x9C: - return "NOKIA_BTS_HW_REQ"; - case 0x9D: - return "NOKIA_BTS_HW_REPORT"; - case 0x9E: - return "NOKIA_BTS_RTE_TEST_REQ"; - case 0x9F: - return "NOKIA_BTS_RTE_TEST_REPORT"; - case 0xA0: - return "NOKIA_BTS_HW_DB_VERIFICATION_REQ"; - case 0xA1: - return "NOKIA_BTS_CLOCK_REQ"; - case 0xA2: - return "NOKIA_AC_CIRCUIT_REQ_NACK"; - case 0xA3: - return "NOKIA_AC_INTERRUPTED"; - case 0xA4: - return "NOKIA_BTS_NEW_TRE_INFO"; - case 0xA5: - return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED"; - case 0xA6: - return "NOKIA_BTS_TRE_POLL_LIST"; - case 0xA7: - return "NOKIA_AC_CIRCUIT_REQ"; - case 0xA8: - return "NOKIA_BTS_BLOCK_CTRL_REQ"; - case 0xA9: - return "NOKIA_BTS_GSM_TIME_REQ"; - case 0xAA: - return "NOKIA_BTS_GSM_TIME"; - case 0xAB: - return "NOKIA_BTS_OUTPUT_CONTROL"; - case 0xAC: - return "NOKIA_BTS_STATE_CHANGED"; - case 0xAD: - return "NOKIA_BTS_SW_SAVE_REQ"; - case 0xAE: - return "NOKIA_BTS_ALARM"; - case 0xAF: - return "NOKIA_BTS_CHA_ADM_STATE"; - case 0xB0: - return "NOKIA_AC_POOL_SIZE_REPORT"; - case 0xB1: - return "NOKIA_AC_POOL_SIZE_INQUIRY"; - case 0xB2: - return "NOKIA_BTS_COMMISS_TEST_COMPLETED"; - case 0xB3: - return "NOKIA_BTS_COMMISS_TEST_REQ"; - case 0xB4: - return "NOKIA_BTS_TRANSP_BTS_TO_BSC"; - case 0xB5: - return "NOKIA_BTS_TRANSP_BSC_TO_BTS"; - case 0xB6: - return "NOKIA_BTS_LCS_COMMAND"; - case 0xB7: - return "NOKIA_BTS_LCS_ANSWER"; - case 0xB8: - return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND"; - case 0xB9: - return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER"; - default: - return "unknown"; - } + switch (msg_type) { + case 0x80: + return "NOKIA_BTS_CONF_DATA"; + case 0x81: + return "NOKIA_BTS_ACK"; + case 0x82: + return "NOKIA_BTS_OMU_STARTED"; + case 0x83: + return "NOKIA_BTS_START_DOWNLOAD_REQ"; + case 0x84: + return "NOKIA_BTS_MF_REQ"; + case 0x85: + return "NOKIA_BTS_AF_REQ"; + case 0x86: + return "NOKIA_BTS_RESET_REQ"; + case 0x87: + return "NOKIA_reserved"; + case 0x88: + return "NOKIA_BTS_CONF_REQ"; + case 0x89: + return "NOKIA_BTS_TEST_REQ"; + case 0x8A: + return "NOKIA_BTS_TEST_REPORT"; + case 0x8B: + return "NOKIA_reserved"; + case 0x8C: + return "NOKIA_reserved"; + case 0x8D: + return "NOKIA_reserved"; + case 0x8E: + return "NOKIA_BTS_CONF_COMPL"; + case 0x8F: + return "NOKIA_reserved"; + case 0x90: + return "NOKIA_BTS_STM_TEST_REQ"; + case 0x91: + return "NOKIA_BTS_STM_TEST_REPORT"; + case 0x92: + return "NOKIA_BTS_TRANSMISSION_COMMAND"; + case 0x93: + return "NOKIA_BTS_TRANSMISSION_ANSWER"; + case 0x94: + return "NOKIA_BTS_HW_DB_UPLOAD_REQ"; + case 0x95: + return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ"; + case 0x96: + return "NOKIA_BTS_HW_DB_SAVE_REQ"; + case 0x97: + return "NOKIA_BTS_FLASH_ERASURE_REQ"; + case 0x98: + return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ"; + case 0x99: + return "NOKIA_BTS_PWR_SUPPLY_CONTROL"; + case 0x9A: + return "NOKIA_BTS_ATTRIBUTE_REQ"; + case 0x9B: + return "NOKIA_BTS_ATTRIBUTE_REPORT"; + case 0x9C: + return "NOKIA_BTS_HW_REQ"; + case 0x9D: + return "NOKIA_BTS_HW_REPORT"; + case 0x9E: + return "NOKIA_BTS_RTE_TEST_REQ"; + case 0x9F: + return "NOKIA_BTS_RTE_TEST_REPORT"; + case 0xA0: + return "NOKIA_BTS_HW_DB_VERIFICATION_REQ"; + case 0xA1: + return "NOKIA_BTS_CLOCK_REQ"; + case 0xA2: + return "NOKIA_AC_CIRCUIT_REQ_NACK"; + case 0xA3: + return "NOKIA_AC_INTERRUPTED"; + case 0xA4: + return "NOKIA_BTS_NEW_TRE_INFO"; + case 0xA5: + return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED"; + case 0xA6: + return "NOKIA_BTS_TRE_POLL_LIST"; + case 0xA7: + return "NOKIA_AC_CIRCUIT_REQ"; + case 0xA8: + return "NOKIA_BTS_BLOCK_CTRL_REQ"; + case 0xA9: + return "NOKIA_BTS_GSM_TIME_REQ"; + case 0xAA: + return "NOKIA_BTS_GSM_TIME"; + case 0xAB: + return "NOKIA_BTS_OUTPUT_CONTROL"; + case 0xAC: + return "NOKIA_BTS_STATE_CHANGED"; + case 0xAD: + return "NOKIA_BTS_SW_SAVE_REQ"; + case 0xAE: + return "NOKIA_BTS_ALARM"; + case 0xAF: + return "NOKIA_BTS_CHA_ADM_STATE"; + case 0xB0: + return "NOKIA_AC_POOL_SIZE_REPORT"; + case 0xB1: + return "NOKIA_AC_POOL_SIZE_INQUIRY"; + case 0xB2: + return "NOKIA_BTS_COMMISS_TEST_COMPLETED"; + case 0xB3: + return "NOKIA_BTS_COMMISS_TEST_REQ"; + case 0xB4: + return "NOKIA_BTS_TRANSP_BTS_TO_BSC"; + case 0xB5: + return "NOKIA_BTS_TRANSP_BSC_TO_BTS"; + case 0xB6: + return "NOKIA_BTS_LCS_COMMAND"; + case 0xB7: + return "NOKIA_BTS_LCS_ANSWER"; + case 0xB8: + return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND"; + case 0xB9: + return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER"; + default: + return "unknown"; + } } static char *get_element_name_string(uint16_t element) { - switch(element) { - case 0x01: - return "Ny1"; - case 0x02: - return "T3105_F"; - case 0x03: - return "Interference band limits"; - case 0x04: - return "Interference report timer in secs"; - case 0x05: - return "Channel configuration per TS"; - case 0x06: - return "BSIC"; - case 0x07: - return "RACH report timer in secs"; - case 0x08: - return "Hardware database status"; - case 0x09: - return "BTS RX level"; - case 0x0A: - return "ARFN"; - case 0x0B: - return "STM antenna attenuation"; - case 0x0C: - return "Cell allocation bitmap"; - case 0x0D: - return "Radio definition per TS"; - case 0x0E: - return "Frame number"; - case 0x0F: - return "Antenna diversity"; - case 0x10: - return "T3105_D"; - case 0x11: - return "File format"; - case 0x12: - return "Last File"; - case 0x13: - return "BTS type"; - case 0x14: - return "Erasure mode"; - case 0x15: - return "Hopping mode"; - case 0x16: - return "Floating TRX"; - case 0x17: - return "Power supplies"; - case 0x18: - return "Reset type"; - case 0x19: - return "Averaging period"; - case 0x1A: - return "RBER2"; - case 0x1B: - return "LAC"; - case 0x1C: - return "CI"; - case 0x1D: - return "Failure parameters"; - case 0x1E: - return "(RF max power reduction)"; - case 0x1F: - return "Measured RX_SENS"; - case 0x20: - return "Extended cell radius"; - case 0x21: - return "reserved"; - case 0x22: - return "Success-Failure"; - case 0x23: - return "Ack-Nack"; - case 0x24: - return "OMU test results"; - case 0x25: - return "File identity"; - case 0x26: - return "Generation and version code"; - case 0x27: - return "SW description"; - case 0x28: - return "BCCH LEV"; - case 0x29: - return "Test type"; - case 0x2A: - return "Subscriber number"; - case 0x2B: - return "reserved"; - case 0x2C: - return "HSN"; - case 0x2D: - return "reserved"; - case 0x2E: - return "MS RXLEV"; - case 0x2F: - return "MS TXLEV"; - case 0x30: - return "RXQUAL"; - case 0x31: - return "RX SENS"; - case 0x32: - return "Alarm block"; - case 0x33: - return "Neighbouring BCCH levels"; - case 0x34: - return "STM report type"; - case 0x35: - return "MA"; - case 0x36: - return "MAIO"; - case 0x37: - return "H_FLAG"; - case 0x38: - return "TCH_ARFN"; - case 0x39: - return "Clock output"; - case 0x3A: - return "Transmitted power"; - case 0x3B: - return "Clock sync"; - case 0x3C: - return "TMS protocol discriminator"; - case 0x3D: - return "TMS protocol data"; - case 0x3E: - return "FER"; - case 0x3F: - return "SWR result"; - case 0x40: - return "Object identity"; - case 0x41: - return "STM RX Antenna Test"; - case 0x42: - return "reserved"; - case 0x43: - return "reserved"; - case 0x44: - return "Object current state"; - case 0x45: - return "reserved"; - case 0x46: - return "FU channel configuration"; - case 0x47: - return "reserved"; - case 0x48: - return "ARFN of a CU"; - case 0x49: - return "FU radio definition"; - case 0x4A: - return "reserved"; - case 0x4B: - return "Severity"; - case 0x4C: - return "Diversity selection"; - case 0x4D: - return "RX antenna test"; - case 0x4E: - return "RX antenna supervision period"; - case 0x4F: - return "RX antenna state"; - case 0x50: - return "Sector configuration"; - case 0x51: - return "Additional info"; - case 0x52: - return "SWR parameters"; - case 0x53: - return "HW inquiry mode"; - case 0x54: - return "reserved"; - case 0x55: - return "Availability status"; - case 0x56: - return "reserved"; - case 0x57: - return "EAC inputs"; - case 0x58: - return "EAC outputs"; - case 0x59: - return "reserved"; - case 0x5A: - return "Position"; - case 0x5B: - return "HW unit identity"; - case 0x5C: - return "RF test signal attenuation"; - case 0x5D: - return "Operational state"; - case 0x5E: - return "Logical object identity"; - case 0x5F: - return "reserved"; - case 0x60: - return "BS_TXPWR_OM"; - case 0x61: - return "Loop_Duration"; - case 0x62: - return "LNA_Path_Selection"; - case 0x63: - return "Serial number"; - case 0x64: - return "HW version"; - case 0x65: - return "Obj. identity and obj. state"; - case 0x66: - return "reserved"; - case 0x67: - return "EAC input definition"; - case 0x68: - return "EAC id and text"; - case 0x69: - return "HW unit status"; - case 0x6A: - return "SW release version"; - case 0x6B: - return "FW version"; - case 0x6C: - return "Bit_Error_Ratio"; - case 0x6D: - return "RXLEV_with_Attenuation"; - case 0x6E: - return "RXLEV_without_Attenuation"; - case 0x6F: - return "reserved"; - case 0x70: - return "CU_Results"; - case 0x71: - return "reserved"; - case 0x72: - return "LNA_Path_Results"; - case 0x73: - return "RTE Results"; - case 0x74: - return "Real Time"; - case 0x75: - return "RX diversity selection"; - case 0x76: - return "EAC input config"; - case 0x77: - return "Feature support"; - case 0x78: - return "File version"; - case 0x79: - return "Outputs"; - case 0x7A: - return "FU parameters"; - case 0x7B: - return "Diagnostic info"; - case 0x7C: - return "FU BSIC"; - case 0x7D: - return "TRX Configuration"; - case 0x7E: - return "Download status"; - case 0x7F: - return "RX difference limit"; - case 0x80: - return "TRX HW capability"; - case 0x81: - return "Common HW config"; - case 0x82: - return "Autoconfiguration pool size"; - case 0x83: - return "TRE diagnostic info"; - case 0x84: - return "TRE object identity"; - case 0x85: - return "New TRE Info"; - case 0x86: - return "Acknowledgement period"; - case 0x87: - return "Synchronization mode"; - case 0x88: - return "reserved"; - case 0x89: - return "Block Control Data"; - case 0x8A: - return "SW load mode"; - case 0x8B: - return "Recommended recovery action"; - case 0x8C: - return "BSC BCF id"; - case 0x8D: - return "Q1 baud rate"; - case 0x8E: - return "Allocation status"; - case 0x8F: - return "Functional entity number"; - case 0x90: - return "Transmission delay"; - case 0x91: - return "Loop Duration ms"; - case 0x92: - return "Logical channel"; - case 0x93: - return "Q1 address"; - case 0x94: - return "Alarm detail"; - case 0x95: - return "Cabinet type"; - case 0x96: - return "HW unit existence"; - case 0x97: - return "RF power parameters"; - case 0x98: - return "Message scenario"; - case 0x99: - return "HW unit max amount"; - case 0x9A: - return "Master TRX"; - case 0x9B: - return "Transparent data"; - case 0x9C: - return "BSC topology info"; - case 0x9D: - return "Air i/f modulation"; - case 0x9E: - return "LCS Q1 command data"; - case 0x9F: - return "Frame number offset"; - case 0xA0: - return "Abis TSL"; - case 0xA1: - return "Dynamic pool info"; - case 0xA2: - return "LCS LLP data"; - case 0xA3: - return "LCS Q1 answer data"; - case 0xA4: - return "DFCA FU Radio Definition"; - case 0xA5: - return "Antenna hopping"; - case 0xA6: - return "Field record sequence number"; - case 0xA7: - return "Timeslot offslot"; - case 0xA8: - return "EPCR capability"; - case 0xA9: - return "Connectsite optional element"; - case 0xAA: - return "TSC"; - case 0xAB: - return "Special TX Power Setting"; - case 0xAC: - return "Optional sync settings"; - case 0xFA: - return "Abis If parameters"; - default: - return "unknown"; - } + switch (element) { + case 0x01: + return "Ny1"; + case 0x02: + return "T3105_F"; + case 0x03: + return "Interference band limits"; + case 0x04: + return "Interference report timer in secs"; + case 0x05: + return "Channel configuration per TS"; + case 0x06: + return "BSIC"; + case 0x07: + return "RACH report timer in secs"; + case 0x08: + return "Hardware database status"; + case 0x09: + return "BTS RX level"; + case 0x0A: + return "ARFN"; + case 0x0B: + return "STM antenna attenuation"; + case 0x0C: + return "Cell allocation bitmap"; + case 0x0D: + return "Radio definition per TS"; + case 0x0E: + return "Frame number"; + case 0x0F: + return "Antenna diversity"; + case 0x10: + return "T3105_D"; + case 0x11: + return "File format"; + case 0x12: + return "Last File"; + case 0x13: + return "BTS type"; + case 0x14: + return "Erasure mode"; + case 0x15: + return "Hopping mode"; + case 0x16: + return "Floating TRX"; + case 0x17: + return "Power supplies"; + case 0x18: + return "Reset type"; + case 0x19: + return "Averaging period"; + case 0x1A: + return "RBER2"; + case 0x1B: + return "LAC"; + case 0x1C: + return "CI"; + case 0x1D: + return "Failure parameters"; + case 0x1E: + return "(RF max power reduction)"; + case 0x1F: + return "Measured RX_SENS"; + case 0x20: + return "Extended cell radius"; + case 0x21: + return "reserved"; + case 0x22: + return "Success-Failure"; + case 0x23: + return "Ack-Nack"; + case 0x24: + return "OMU test results"; + case 0x25: + return "File identity"; + case 0x26: + return "Generation and version code"; + case 0x27: + return "SW description"; + case 0x28: + return "BCCH LEV"; + case 0x29: + return "Test type"; + case 0x2A: + return "Subscriber number"; + case 0x2B: + return "reserved"; + case 0x2C: + return "HSN"; + case 0x2D: + return "reserved"; + case 0x2E: + return "MS RXLEV"; + case 0x2F: + return "MS TXLEV"; + case 0x30: + return "RXQUAL"; + case 0x31: + return "RX SENS"; + case 0x32: + return "Alarm block"; + case 0x33: + return "Neighbouring BCCH levels"; + case 0x34: + return "STM report type"; + case 0x35: + return "MA"; + case 0x36: + return "MAIO"; + case 0x37: + return "H_FLAG"; + case 0x38: + return "TCH_ARFN"; + case 0x39: + return "Clock output"; + case 0x3A: + return "Transmitted power"; + case 0x3B: + return "Clock sync"; + case 0x3C: + return "TMS protocol discriminator"; + case 0x3D: + return "TMS protocol data"; + case 0x3E: + return "FER"; + case 0x3F: + return "SWR result"; + case 0x40: + return "Object identity"; + case 0x41: + return "STM RX Antenna Test"; + case 0x42: + return "reserved"; + case 0x43: + return "reserved"; + case 0x44: + return "Object current state"; + case 0x45: + return "reserved"; + case 0x46: + return "FU channel configuration"; + case 0x47: + return "reserved"; + case 0x48: + return "ARFN of a CU"; + case 0x49: + return "FU radio definition"; + case 0x4A: + return "reserved"; + case 0x4B: + return "Severity"; + case 0x4C: + return "Diversity selection"; + case 0x4D: + return "RX antenna test"; + case 0x4E: + return "RX antenna supervision period"; + case 0x4F: + return "RX antenna state"; + case 0x50: + return "Sector configuration"; + case 0x51: + return "Additional info"; + case 0x52: + return "SWR parameters"; + case 0x53: + return "HW inquiry mode"; + case 0x54: + return "reserved"; + case 0x55: + return "Availability status"; + case 0x56: + return "reserved"; + case 0x57: + return "EAC inputs"; + case 0x58: + return "EAC outputs"; + case 0x59: + return "reserved"; + case 0x5A: + return "Position"; + case 0x5B: + return "HW unit identity"; + case 0x5C: + return "RF test signal attenuation"; + case 0x5D: + return "Operational state"; + case 0x5E: + return "Logical object identity"; + case 0x5F: + return "reserved"; + case 0x60: + return "BS_TXPWR_OM"; + case 0x61: + return "Loop_Duration"; + case 0x62: + return "LNA_Path_Selection"; + case 0x63: + return "Serial number"; + case 0x64: + return "HW version"; + case 0x65: + return "Obj. identity and obj. state"; + case 0x66: + return "reserved"; + case 0x67: + return "EAC input definition"; + case 0x68: + return "EAC id and text"; + case 0x69: + return "HW unit status"; + case 0x6A: + return "SW release version"; + case 0x6B: + return "FW version"; + case 0x6C: + return "Bit_Error_Ratio"; + case 0x6D: + return "RXLEV_with_Attenuation"; + case 0x6E: + return "RXLEV_without_Attenuation"; + case 0x6F: + return "reserved"; + case 0x70: + return "CU_Results"; + case 0x71: + return "reserved"; + case 0x72: + return "LNA_Path_Results"; + case 0x73: + return "RTE Results"; + case 0x74: + return "Real Time"; + case 0x75: + return "RX diversity selection"; + case 0x76: + return "EAC input config"; + case 0x77: + return "Feature support"; + case 0x78: + return "File version"; + case 0x79: + return "Outputs"; + case 0x7A: + return "FU parameters"; + case 0x7B: + return "Diagnostic info"; + case 0x7C: + return "FU BSIC"; + case 0x7D: + return "TRX Configuration"; + case 0x7E: + return "Download status"; + case 0x7F: + return "RX difference limit"; + case 0x80: + return "TRX HW capability"; + case 0x81: + return "Common HW config"; + case 0x82: + return "Autoconfiguration pool size"; + case 0x83: + return "TRE diagnostic info"; + case 0x84: + return "TRE object identity"; + case 0x85: + return "New TRE Info"; + case 0x86: + return "Acknowledgement period"; + case 0x87: + return "Synchronization mode"; + case 0x88: + return "reserved"; + case 0x89: + return "Block Control Data"; + case 0x8A: + return "SW load mode"; + case 0x8B: + return "Recommended recovery action"; + case 0x8C: + return "BSC BCF id"; + case 0x8D: + return "Q1 baud rate"; + case 0x8E: + return "Allocation status"; + case 0x8F: + return "Functional entity number"; + case 0x90: + return "Transmission delay"; + case 0x91: + return "Loop Duration ms"; + case 0x92: + return "Logical channel"; + case 0x93: + return "Q1 address"; + case 0x94: + return "Alarm detail"; + case 0x95: + return "Cabinet type"; + case 0x96: + return "HW unit existence"; + case 0x97: + return "RF power parameters"; + case 0x98: + return "Message scenario"; + case 0x99: + return "HW unit max amount"; + case 0x9A: + return "Master TRX"; + case 0x9B: + return "Transparent data"; + case 0x9C: + return "BSC topology info"; + case 0x9D: + return "Air i/f modulation"; + case 0x9E: + return "LCS Q1 command data"; + case 0x9F: + return "Frame number offset"; + case 0xA0: + return "Abis TSL"; + case 0xA1: + return "Dynamic pool info"; + case 0xA2: + return "LCS LLP data"; + case 0xA3: + return "LCS Q1 answer data"; + case 0xA4: + return "DFCA FU Radio Definition"; + case 0xA5: + return "Antenna hopping"; + case 0xA6: + return "Field record sequence number"; + case 0xA7: + return "Timeslot offslot"; + case 0xA8: + return "EPCR capability"; + case 0xA9: + return "Connectsite optional element"; + case 0xAA: + return "TSC"; + case 0xAB: + return "Special TX Power Setting"; + case 0xAC: + return "Optional sync settings"; + case 0xFA: + return "Abis If parameters"; + default: + return "unknown"; + } } static char *get_bts_type_string(uint8_t type) { - switch(type) { - case 0x0A: - return "MetroSite GSM 900"; - case 0x0B: - return "MetroSite GSM 1800"; - case 0x0C: - return "MetroSite GSM 1900 (PCS)"; - case 0x0D: - return "MetroSite GSM 900 & 1800"; - case 0x0E: - return "InSite GSM 900"; - case 0x0F: - return "InSite GSM 1800"; - case 0x10: - return "InSite GSM 1900"; - case 0x11: - return "UltraSite GSM 900"; - case 0x12: - return "UltraSite GSM 1800"; - case 0x13: - return "UltraSite GSM/US-TDMA 1900"; - case 0x14: - return "UltraSite GSM 900 & 1800"; - case 0x16: - return "UltraSite GSM/US-TDMA 850"; - case 0x18: - return "MetroSite GSM/US-TDMA 850"; - case 0x19: - return "UltraSite GSM 800/1900"; - default: - return "unknown"; - } + switch (type) { + case 0x0A: + return "MetroSite GSM 900"; + case 0x0B: + return "MetroSite GSM 1800"; + case 0x0C: + return "MetroSite GSM 1900 (PCS)"; + case 0x0D: + return "MetroSite GSM 900 & 1800"; + case 0x0E: + return "InSite GSM 900"; + case 0x0F: + return "InSite GSM 1800"; + case 0x10: + return "InSite GSM 1900"; + case 0x11: + return "UltraSite GSM 900"; + case 0x12: + return "UltraSite GSM 1800"; + case 0x13: + return "UltraSite GSM/US-TDMA 1900"; + case 0x14: + return "UltraSite GSM 900 & 1800"; + case 0x16: + return "UltraSite GSM/US-TDMA 850"; + case 0x18: + return "MetroSite GSM/US-TDMA 850"; + case 0x19: + return "UltraSite GSM 800/1900"; + default: + return "unknown"; + } } static char *get_severity_string(uint8_t severity) { - switch(severity) { - case 0: - return "indeterminate"; - case 1: - return "critical"; - case 2: - return "major"; - case 3: - return "minor"; - case 4: - return "warning"; - default: - return "unknown"; - } + switch (severity) { + case 0: + return "indeterminate"; + case 1: + return "critical"; + case 2: + return "major"; + case 3: + return "minor"; + case 4: + return "warning"; + default: + return "unknown"; + } } /* TODO: put in a separate file ? */ @@ -755,178 +758,172 @@ static char *get_severity_string(uint8_t severity) #define OM_ALLOC_SIZE 1024 #define OM_HEADROOM_SIZE 128 -static uint8_t fu_config_template[] = -{ - 0x7F, 0x7A, 0x39, - /* ID = 0x7A (FU parameters) ## constructed ## */ - /* length = 57 */ - /* [3] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [6] */ - 0x00, 0x07, 0x01, 0xFF, - - 0x41, 0x02, - /* ID = 0x01 (Ny1) */ - /* length = 2 */ - /* [12] */ - 0x00, 0x05, - - 0x42, 0x02, - /* ID = 0x02 (T3105_F) */ - /* length = 2 */ - /* [16] */ - 0x00, 0x28, - - 0x50, 0x02, - /* ID = 0x10 (T3105_D) */ - /* length = 2 */ - /* [20] */ - 0x00, 0x28, - - 0x43, 0x05, - /* ID = 0x03 (Interference band limits) */ - /* length = 5 */ - /* [24] */ - 0x0F, 0x1B, 0x27, 0x33, 0x3F, - - 0x44, 0x02, - /* ID = 0x04 (Interference report timer in secs) */ - /* length = 2 */ - /* [31] */ - 0x00, 0x10, - - 0x47, 0x01, - /* ID = 0x07 (RACH report timer in secs) */ - /* length = 1 */ - /* [35] */ - 0x1E, - - 0x4C, 0x10, - /* ID = 0x0C (Cell allocation bitmap) ####### */ - /* length = 16 */ - /* [38] */ - 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - - 0x59, 0x01, - /* ID = 0x19 (Averaging period) */ - /* length = 1 */ - /* [56] */ - 0x01, - - 0x5E, 0x01, - /* ID = 0x1E ((RF max power reduction)) */ - /* length = 1 */ - /* [59] */ - 0x00, - - - 0x7F, 0x46, 0x11, - /* ID = 0x46 (FU channel configuration) ## constructed ## */ - /* length = 17 */ - /* [63] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [66] */ - 0x00, 0x07, 0x01, 0xFF, - - 0x45, 0x08, - /* ID = 0x05 (Channel configuration per TS) */ - /* length = 8 */ - /* [72] */ - 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, - - - 0x7F, 0x65, 0x0B, - /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */ - /* length = 11 */ - /* [83] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [86] */ - 0x00, 0x04, 0x01, 0xFF, - - 0x5F, 0x44, 0x01, - /* ID = 0x44 (Object current state) */ - /* length = 1 */ - /* [93] */ - 0x03, - - - 0x7F, 0x7C, 0x0A, - /* ID = 0x7C (FU BSIC) ## constructed ## */ - /* length = 10 */ - /* [97] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [100] */ - 0x00, 0x07, 0x01, 0xFF, - - 0x46, 0x01, - /* ID = 0x06 (BSIC) */ - /* length = 1 */ - /* [106] */ - 0x00, - - - 0x7F, 0x48, 0x0B, - /* ID = 0x48 (ARFN of a CU) ## constructed ## */ - /* length = 11 */ - /* [110] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [113] */ - 0x00, 0x08, 0x01, 0xFF, - - 0x4A, 0x02, - /* ID = 0x0A (ARFN) ####### */ - /* length = 2 */ - /* [119] */ - 0x03, 0x62, - - - 0x7F, 0x49, 0x59, - /* ID = 0x49 (FU radio definition) ## constructed ## */ - /* length = 89 */ - /* [124] */ - - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [127] */ - 0x00, 0x07, 0x01, 0xFF, - - 0x4D, 0x50, - /* ID = 0x0D (Radio definition per TS) ####### */ - /* length = 80 */ - /* [133] */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */ - 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x62, +static uint8_t fu_config_template[] = { + 0x7F, 0x7A, 0x39, + /* ID = 0x7A (FU parameters) ## constructed ## */ + /* length = 57 */ + /* [3] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [6] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x41, 0x02, + /* ID = 0x01 (Ny1) */ + /* length = 2 */ + /* [12] */ + 0x00, 0x05, + + 0x42, 0x02, + /* ID = 0x02 (T3105_F) */ + /* length = 2 */ + /* [16] */ + 0x00, 0x28, + + 0x50, 0x02, + /* ID = 0x10 (T3105_D) */ + /* length = 2 */ + /* [20] */ + 0x00, 0x28, + + 0x43, 0x05, + /* ID = 0x03 (Interference band limits) */ + /* length = 5 */ + /* [24] */ + 0x0F, 0x1B, 0x27, 0x33, 0x3F, + + 0x44, 0x02, + /* ID = 0x04 (Interference report timer in secs) */ + /* length = 2 */ + /* [31] */ + 0x00, 0x10, + + 0x47, 0x01, + /* ID = 0x07 (RACH report timer in secs) */ + /* length = 1 */ + /* [35] */ + 0x1E, + + 0x4C, 0x10, + /* ID = 0x0C (Cell allocation bitmap) ####### */ + /* length = 16 */ + /* [38] */ + 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x59, 0x01, + /* ID = 0x19 (Averaging period) */ + /* length = 1 */ + /* [56] */ + 0x01, + + 0x5E, 0x01, + /* ID = 0x1E ((RF max power reduction)) */ + /* length = 1 */ + /* [59] */ + 0x00, + + 0x7F, 0x46, 0x11, + /* ID = 0x46 (FU channel configuration) ## constructed ## */ + /* length = 17 */ + /* [63] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [66] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x45, 0x08, + /* ID = 0x05 (Channel configuration per TS) */ + /* length = 8 */ + /* [72] */ + 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, + + 0x7F, 0x65, 0x0B, + /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */ + /* length = 11 */ + /* [83] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [86] */ + 0x00, 0x04, 0x01, 0xFF, + + 0x5F, 0x44, 0x01, + /* ID = 0x44 (Object current state) */ + /* length = 1 */ + /* [93] */ + 0x03, + + 0x7F, 0x7C, 0x0A, + /* ID = 0x7C (FU BSIC) ## constructed ## */ + /* length = 10 */ + /* [97] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [100] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x46, 0x01, + /* ID = 0x06 (BSIC) */ + /* length = 1 */ + /* [106] */ + 0x00, + + 0x7F, 0x48, 0x0B, + /* ID = 0x48 (ARFN of a CU) ## constructed ## */ + /* length = 11 */ + /* [110] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [113] */ + 0x00, 0x08, 0x01, 0xFF, + + 0x4A, 0x02, + /* ID = 0x0A (ARFN) ####### */ + /* length = 2 */ + /* [119] */ + 0x03, 0x62, + + 0x7F, 0x49, 0x59, + /* ID = 0x49 (FU radio definition) ## constructed ## */ + /* length = 89 */ + /* [124] */ + + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [127] */ + 0x00, 0x07, 0x01, 0xFF, + + 0x4D, 0x50, + /* ID = 0x0D (Radio definition per TS) ####### */ + /* length = 80 */ + /* [133] */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */ + 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x62, }; /* TODO: put in a separate file ? */ @@ -935,288 +932,287 @@ static uint8_t fu_config_template[] = build the configuration for each TRX */ -static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, uint8_t *fu_config, int *hopping) +static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, + uint8_t * fu_config, int *hopping) { - int i; - - *hopping = 0; - - memcpy(fu_config, fu_config_template, sizeof(fu_config_template)); - - /* set ID */ - - fu_config[ 6 + 2] = id; - fu_config[ 66 + 2] = id; - fu_config[ 86 + 2] = id; - fu_config[100 + 2] = id; - fu_config[113 + 2] = id; - fu_config[127 + 2] = id; - - /* set ARFCN */ - - uint16_t arfcn = trx->arfcn; - - fu_config[119] = arfcn >> 8; - fu_config[119 + 1] = arfcn & 0xFF; - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - struct gsm_bts_trx_ts *ts = &trx->ts[i]; - - if (ts->hopping.enabled) { - /* reverse order */ - int j; - for(j = 0; j < ts->hopping.ma_len; j++) - fu_config[133 + (i * 10) + (7 - j)] = ts->hopping.ma_data[j]; - fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn; - fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio; - *hopping = 1; - } else { - fu_config[133 + 8 + (i * 10)] = arfcn >> 8; - fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF; - } - } - - /* set BSIC */ - - /* - Attention: all TRX except the first one seem to get the TSC - from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION, - GSM 04.08 CHANNEL DESCRIPTION). - There was a bug in rsl_chan_activate_lchan() setting this parameter. - */ - - uint8_t bsic = trx->bts->bsic; - - fu_config[106] = bsic; - - /* set CA */ - - if(generate_cell_chan_list(&fu_config[38], trx->bts) != 0) { - fprintf(stderr, "generate_cell_chan_list failed\n"); - return 0; - } - - /* set channel configuration */ - - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - struct gsm_bts_trx_ts *ts = &trx->ts[i]; - uint8_t chan_config; - - /* - 0 = FCCH + SCH + BCCH + CCCH - 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4 - 2 = BCCH + CCCH (This combination is not used in any BTS) - 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH - 4 = SDCCH/8 + SACCH/8 - 5 = SDCCH/8 with SDCCH2 used as CBCH - 6 = TCH/F + FACCH/F + SACCH/F - 7 = E-RACH (Talk family) - 9 = Dual rate (capability for TCH/F and TCH/H) - 10 = reserved for BTS internal use - 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (This channel configuration type can be used in GPRS release 2). - 0xFF = spare TS - */ - - if(ts->pchan == GSM_PCHAN_NONE) - chan_config = 0xFF; - else if(ts->pchan == GSM_PCHAN_CCCH) - chan_config = 0; - else if(ts->pchan == GSM_PCHAN_CCCH_SDCCH4) - chan_config = 1; - else if(ts->pchan == GSM_PCHAN_TCH_F) - chan_config = 6; /* 9 should work too */ - else if(ts->pchan == GSM_PCHAN_TCH_H) - chan_config = 9; - else if(ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C) - chan_config = 4; - else if(ts->pchan == GSM_PCHAN_PDCH) - chan_config = 11; - else { - fprintf(stderr, "unsupported channel config %d for timeslot %d\n", ts->pchan, i); - return 0; - } - - fu_config[72 + i] = chan_config; - } - return sizeof(fu_config_template); + int i; + + *hopping = 0; + + memcpy(fu_config, fu_config_template, sizeof(fu_config_template)); + + /* set ID */ + + fu_config[6 + 2] = id; + fu_config[66 + 2] = id; + fu_config[86 + 2] = id; + fu_config[100 + 2] = id; + fu_config[113 + 2] = id; + fu_config[127 + 2] = id; + + /* set ARFCN */ + + uint16_t arfcn = trx->arfcn; + + fu_config[119] = arfcn >> 8; + fu_config[119 + 1] = arfcn & 0xFF; + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + + if (ts->hopping.enabled) { + /* reverse order */ + int j; + for (j = 0; j < ts->hopping.ma_len; j++) + fu_config[133 + (i * 10) + (7 - j)] = + ts->hopping.ma_data[j]; + fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn; + fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio; + *hopping = 1; + } else { + fu_config[133 + 8 + (i * 10)] = arfcn >> 8; + fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF; + } + } + + /* set BSIC */ + + /* + Attention: all TRX except the first one seem to get the TSC + from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION, + GSM 04.08 CHANNEL DESCRIPTION). + There was a bug in rsl_chan_activate_lchan() setting this parameter. + */ + + uint8_t bsic = trx->bts->bsic; + + fu_config[106] = bsic; + + /* set CA */ + + if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) { + fprintf(stderr, "generate_cell_chan_list failed\n"); + return 0; + } + + /* set channel configuration */ + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + uint8_t chan_config; + + /* + 0 = FCCH + SCH + BCCH + CCCH + 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4 + 2 = BCCH + CCCH (This combination is not used in any BTS) + 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH + 4 = SDCCH/8 + SACCH/8 + 5 = SDCCH/8 with SDCCH2 used as CBCH + 6 = TCH/F + FACCH/F + SACCH/F + 7 = E-RACH (Talk family) + 9 = Dual rate (capability for TCH/F and TCH/H) + 10 = reserved for BTS internal use + 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (This channel configuration type can be used in GPRS release 2). + 0xFF = spare TS + */ + + if (ts->pchan == GSM_PCHAN_NONE) + chan_config = 0xFF; + else if (ts->pchan == GSM_PCHAN_CCCH) + chan_config = 0; + else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4) + chan_config = 1; + else if (ts->pchan == GSM_PCHAN_TCH_F) + chan_config = 6; /* 9 should work too */ + else if (ts->pchan == GSM_PCHAN_TCH_H) + chan_config = 9; + else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C) + chan_config = 4; + else if (ts->pchan == GSM_PCHAN_PDCH) + chan_config = 11; + else { + fprintf(stderr, + "unsupported channel config %d for timeslot %d\n", + ts->pchan, i); + return 0; + } + + fu_config[72 + i] = chan_config; + } + return sizeof(fu_config_template); } /* TODO: put in a separate file ? */ -static uint8_t bts_config_1[] = -{ - 0x4E, 0x02, - /* ID = 0x0E (Frame number) */ - /* length = 2 */ - /* [2] */ - 0xFF, 0xFF, - - 0x5F, 0x4E, 0x02, - /* ID = 0x4E (RX antenna supervision period) */ - /* length = 2 */ - /* [7] */ - 0xFF, 0xFF, - - 0x5F, 0x50, 0x02, - /* ID = 0x50 (Sector configuration) */ - /* length = 2 */ - /* [12] */ - 0x01, 0x01, +static uint8_t bts_config_1[] = { + 0x4E, 0x02, + /* ID = 0x0E (Frame number) */ + /* length = 2 */ + /* [2] */ + 0xFF, 0xFF, + + 0x5F, 0x4E, 0x02, + /* ID = 0x4E (RX antenna supervision period) */ + /* length = 2 */ + /* [7] */ + 0xFF, 0xFF, + + 0x5F, 0x50, 0x02, + /* ID = 0x50 (Sector configuration) */ + /* length = 2 */ + /* [12] */ + 0x01, 0x01, }; -static uint8_t bts_config_2[] = -{ - 0x55, 0x02, - /* ID = 0x15 (Hopping mode) */ - /* length = 2 */ - /* [2] */ - 0x01, 0x00, - - 0x5F, 0x75, 0x02, - /* ID = 0x75 (RX diversity selection) */ - /* length = 2 */ - /* [7] */ - 0x01, 0x01, +static uint8_t bts_config_2[] = { + 0x55, 0x02, + /* ID = 0x15 (Hopping mode) */ + /* length = 2 */ + /* [2] */ + 0x01, 0x00, + + 0x5F, 0x75, 0x02, + /* ID = 0x75 (RX diversity selection) */ + /* length = 2 */ + /* [7] */ + 0x01, 0x01, }; -static uint8_t bts_config_3[] = -{ - 0x5F, 0x20, 0x02, - /* ID = 0x20 (Extended cell radius) */ - /* length = 2 */ - /* [3] */ - 0x01, 0x00, +static uint8_t bts_config_3[] = { + 0x5F, 0x20, 0x02, + /* ID = 0x20 (Extended cell radius) */ + /* length = 2 */ + /* [3] */ + 0x01, 0x00, }; -static uint8_t bts_config_4[] = -{ - 0x5F, 0x74, 0x09, - /* ID = 0x74 (Real Time) */ - /* length = 9 */ - /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ - 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00, - 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [15] */ - 0x01, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [21] */ - 0x02, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [27] */ - 0x03, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [33] */ - 0x04, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [39] */ - 0x05, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [45] */ - 0x06, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [51] */ - 0x07, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [57] */ - 0x08, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [63] */ - 0x09, 0x01, 0x00, - - 0x5F, 0x76, 0x03, - /* ID = 0x76 (EAC input config) */ - /* length = 3 */ - /* [69] */ - 0x0A, 0x01, 0x00, +static uint8_t bts_config_4[] = { + 0x5F, 0x74, 0x09, + /* ID = 0x74 (Real Time) */ + /* length = 9 */ + /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ + 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00, + 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [15] */ + 0x01, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [21] */ + 0x02, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [27] */ + 0x03, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [33] */ + 0x04, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [39] */ + 0x05, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [45] */ + 0x06, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [51] */ + 0x07, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [57] */ + 0x08, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [63] */ + 0x09, 0x01, 0x00, + + 0x5F, 0x76, 0x03, + /* ID = 0x76 (EAC input config) */ + /* length = 3 */ + /* [69] */ + 0x0A, 0x01, 0x00, }; -static uint8_t bts_config_insite[] = -{ - 0x4E, 0x02, - /* ID = 0x0E (Frame number) */ - /* length = 2 */ - /* [2] */ - 0xFF, 0xFF, - - 0x5F, 0x4E, 0x02, - /* ID = 0x4E (RX antenna supervision period) */ - /* length = 2 */ - /* [7] */ - 0xFF, 0xFF, - - 0x5F, 0x50, 0x02, - /* ID = 0x50 (Sector configuration) */ - /* length = 2 */ - /* [12] */ - 0x01, 0x01, - - 0x55, 0x02, - /* ID = 0x15 (Hopping mode) */ - /* length = 2 */ - /* [16] */ - 0x01, 0x00, - - 0x5F, 0x20, 0x02, - /* ID = 0x20 (Extended cell radius) */ - /* length = 2 */ - /* [21] */ - 0x01, 0x00, - - 0x5F, 0x74, 0x09, - /* ID = 0x74 (Real Time) */ - /* length = 9 */ - /* [26] */ - 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00, - 0x00, +static uint8_t bts_config_insite[] = { + 0x4E, 0x02, + /* ID = 0x0E (Frame number) */ + /* length = 2 */ + /* [2] */ + 0xFF, 0xFF, + + 0x5F, 0x4E, 0x02, + /* ID = 0x4E (RX antenna supervision period) */ + /* length = 2 */ + /* [7] */ + 0xFF, 0xFF, + + 0x5F, 0x50, 0x02, + /* ID = 0x50 (Sector configuration) */ + /* length = 2 */ + /* [12] */ + 0x01, 0x01, + + 0x55, 0x02, + /* ID = 0x15 (Hopping mode) */ + /* length = 2 */ + /* [16] */ + 0x01, 0x00, + + 0x5F, 0x20, 0x02, + /* ID = 0x20 (Extended cell radius) */ + /* length = 2 */ + /* [21] */ + 0x01, 0x00, + + 0x5F, 0x74, 0x09, + /* ID = 0x74 (Real Time) */ + /* length = 9 */ + /* [26] */ + 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00, + 0x00, }; -void set_real_time(uint8_t *real_time) +void set_real_time(uint8_t * real_time) { - time_t t; - struct tm *tm; - - t = time(NULL); - tm = localtime(&t); - - /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ - - real_time[0] = (1900 + tm->tm_year) >> 8; - real_time[1] = (1900 + tm->tm_year) & 0xFF; - real_time[2] = tm->tm_mon + 1; - real_time[3] = tm->tm_mday; - real_time[4] = tm->tm_hour; - real_time[5] = tm->tm_min; - real_time[6] = tm->tm_sec; - real_time[7] = 0; - real_time[8] = 0; + time_t t; + struct tm *tm; + + t = time(NULL); + tm = localtime(&t); + + /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */ + + real_time[0] = (1900 + tm->tm_year) >> 8; + real_time[1] = (1900 + tm->tm_year) & 0xFF; + real_time[2] = tm->tm_mon + 1; + real_time[3] = tm->tm_mday; + real_time[4] = tm->tm_hour; + real_time[5] = tm->tm_min; + real_time[6] = tm->tm_sec; + real_time[7] = 0; + real_time[8] = 0; } /* TODO: put in a separate file ? */ @@ -1227,423 +1223,438 @@ void set_real_time(uint8_t *real_time) */ -static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t *fu_config, int need_hopping) +static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config, + int need_hopping) { - /* is it an InSite BTS ? */ - if(bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */ - if(n_trx != 1) { - fprintf(stderr, "InSite has only one TRX\n"); - return 0; - } - if(need_hopping != 0) { - fprintf(stderr, "InSite does not support hopping\n"); - return 0; - } - memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite)); - set_real_time(&fu_config[26]); - return sizeof(bts_config_insite); - } - - int len = 0; - int i; - - memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1)); - - /* set sector configuration */ - fu_config[len + 12 - 1] = 1 + n_trx; /* len */ - for(i = 0; i < n_trx; i++) - fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF); - - len += (sizeof(bts_config_1) + (n_trx - 1)); - - memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2)); - /* set hopping mode (Baseband and RF hopping work for the MetroSite) */ - if(need_hopping) - fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */ - len += sizeof(bts_config_2); - - /* set extended cell radius for each TRX */ - for(i = 0; i < n_trx; i++) { - memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3)); - fu_config[len + 3] = ((i + 1) & 0xFF); - len += sizeof(bts_config_3); - } - - memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4)); - set_real_time(&fu_config[len + 3]); - len += sizeof(bts_config_4); - - return len; + /* is it an InSite BTS ? */ + if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */ + if (n_trx != 1) { + fprintf(stderr, "InSite has only one TRX\n"); + return 0; + } + if (need_hopping != 0) { + fprintf(stderr, "InSite does not support hopping\n"); + return 0; + } + memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite)); + set_real_time(&fu_config[26]); + return sizeof(bts_config_insite); + } + + int len = 0; + int i; + + memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1)); + + /* set sector configuration */ + fu_config[len + 12 - 1] = 1 + n_trx; /* len */ + for (i = 0; i < n_trx; i++) + fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF); + + len += (sizeof(bts_config_1) + (n_trx - 1)); + + memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2)); + /* set hopping mode (Baseband and RF hopping work for the MetroSite) */ + if (need_hopping) + fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */ + len += sizeof(bts_config_2); + + /* set extended cell radius for each TRX */ + for (i = 0; i < n_trx; i++) { + memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3)); + fu_config[len + 3] = ((i + 1) & 0xFF); + len += sizeof(bts_config_3); + } + + memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4)); + set_real_time(&fu_config[len + 3]); + len += sizeof(bts_config_4); + + return len; } /* TODO: put in a separate file ? */ static struct msgb *nm_msgb_alloc(void) { - return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, - "OML"); + return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML"); } /* TODO: put in a separate file ? */ struct abis_om_nokia_hdr { - uint8_t msg_type; - uint8_t spare; - uint16_t reference; - uint8_t data[0]; + uint8_t msg_type; + uint8_t spare; + uint16_t reference; + uint8_t data[0]; } __attribute__ ((packed)); #define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr)) -static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref, uint8_t *data, int len_data) +static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref, + uint8_t * data, int len_data) { - struct abis_om_hdr *oh; - struct abis_om_nokia_hdr *noh; - struct msgb *msg = nm_msgb_alloc(); - - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_NOKIA_HDR_SIZE + len_data); - - oh->mdisc = ABIS_OM_MDISC_FOM; - oh->placement = ABIS_OM_PLACEMENT_ONLY; - oh->sequence = 0; - oh->length = sizeof(struct abis_om_nokia_hdr) + len_data; - - noh = (struct abis_om_nokia_hdr *)oh->data; - - noh->msg_type = msg_type; - noh->spare = 0; - noh->reference = htons(ref); - memcpy(noh->data, data, len_data); - - DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type)); - - return abis_nm_sendmsg(bts, msg); + struct abis_om_hdr *oh; + struct abis_om_nokia_hdr *noh; + struct msgb *msg = nm_msgb_alloc(); + + oh = (struct abis_om_hdr *)msgb_put(msg, + ABIS_OM_NOKIA_HDR_SIZE + len_data); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_ONLY; + oh->sequence = 0; + oh->length = sizeof(struct abis_om_nokia_hdr) + len_data; + + noh = (struct abis_om_nokia_hdr *)oh->data; + + noh->msg_type = msg_type; + noh->spare = 0; + noh->reference = htons(ref); + memcpy(noh->data, data, len_data); + + DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type)); + + return abis_nm_sendmsg(bts, msg); } /* TODO: put in a separate file ? */ static uint8_t download_req[] = { - 0x5F, 0x25, 0x0B, - /* ID = 0x25 (File identity) */ - /* length = 11 */ - /* [3] */ - 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, - 0x2A, 0x2A, 0x2A, - - 0x5F, 0x78, 0x03, - /* ID = 0x78 (File version) */ - /* length = 3 */ - /* [17] */ - 0x2A, 0x2A, 0x2A, - - 0x5F, 0x81, 0x0A, 0x01, - /* ID = 0x8A (SW load mode) */ - /* length = 1 */ - /* [24] */ - 0x01, - - 0x5F, 0x81, 0x06, 0x01, - /* ID = 0x86 (Acknowledgement period) */ - /* length = 1 */ - /* [29] */ - 0x01, + 0x5F, 0x25, 0x0B, + /* ID = 0x25 (File identity) */ + /* length = 11 */ + /* [3] */ + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x2A, 0x2A, 0x2A, + + 0x5F, 0x78, 0x03, + /* ID = 0x78 (File version) */ + /* length = 3 */ + /* [17] */ + 0x2A, 0x2A, 0x2A, + + 0x5F, 0x81, 0x0A, 0x01, + /* ID = 0x8A (SW load mode) */ + /* length = 1 */ + /* [24] */ + 0x01, + + 0x5F, 0x81, 0x06, 0x01, + /* ID = 0x86 (Acknowledgement period) */ + /* length = 1 */ + /* [29] */ + 0x01, }; static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref) { - uint8_t *data = download_req; - int len_data = sizeof(download_req); - - return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data, len_data); + uint8_t *data = download_req; + int len_data = sizeof(download_req); + + return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data, + len_data); } /* TODO: put in a separate file ? */ static uint8_t ack[] = { - 0x5F, 0x23, 0x01, - /* ID = 0x23 (Ack-Nack) */ - /* length = 1 */ - /* [3] */ - 0x01, + 0x5F, 0x23, 0x01, + /* ID = 0x23 (Ack-Nack) */ + /* length = 1 */ + /* [3] */ + 0x01, }; static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref) { - uint8_t *data = ack; - int len_data = sizeof(ack); - - return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data); + uint8_t *data = ack; + int len_data = sizeof(ack); + + return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data); } /* TODO: put in a separate file ? */ static uint8_t reset[] = { - 0x5F, 0x40, 0x04, - /* ID = 0x40 (Object identity) */ - /* length = 4 */ - /* [3] */ - 0x00, 0x01, 0xFF, 0xFF, + 0x5F, 0x40, 0x04, + /* ID = 0x40 (Object identity) */ + /* length = 4 */ + /* [3] */ + 0x00, 0x01, 0xFF, 0xFF, }; static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref) { - uint8_t *data = reset; - int len_data = sizeof(reset); - - return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data); + uint8_t *data = reset; + int len_data = sizeof(reset); + + return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data); } /* TODO: put in a separate file ? */ -static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref, uint8_t *data, int len) +static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type, + uint16_t ref, uint8_t * data, int len) { - int len_remain, len_to_send, max_send; - int seq = 0; - int ret; - - len_remain = len; - - while(len_remain) { - struct abis_om_hdr *oh; - struct abis_om_nokia_hdr *noh; - struct msgb *msg = nm_msgb_alloc(); - - if(seq == 0) - max_send = 256 - sizeof(struct abis_om_nokia_hdr); - else - max_send = 256; - - if(len_remain > max_send) { - len_to_send = max_send; - - if(seq == 0) { - /* first segment */ - oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_NOKIA_HDR_SIZE + len_to_send); - - oh->mdisc = ABIS_OM_MDISC_FOM; - oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */ - oh->sequence = seq; - oh->length = 0; /* 256 bytes */ - - noh = (struct abis_om_nokia_hdr *)oh->data; - - noh->msg_type = msg_type; - noh->spare = 0; - noh->reference = htons(ref); - memcpy(noh->data, data, len_to_send); - } else { - /* segment in between */ - oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(struct abis_om_hdr) + len_to_send); - - oh->mdisc = ABIS_OM_MDISC_FOM; - oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */ - oh->sequence = seq; - oh->length = 0; /* 256 bytes */ - - memcpy(oh->data, data, len_to_send); - } - } - else { - - len_to_send = len_remain; - - /* check if message fits in a single segment */ - - if(seq == 0) - return abis_nm_send(bts, msg_type, ref, data, len_to_send); - - /* last segment */ - - oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(struct abis_om_hdr) + len_to_send); - - oh->mdisc = ABIS_OM_MDISC_FOM; - oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */ - oh->sequence = seq; - oh->length = len_to_send; - - memcpy(oh->data, data, len_to_send); - } - - DEBUGPC(DNM, "Sending multi-segment %d\n", seq); - - ret = abis_nm_sendmsg(bts, msg); - if(ret < 0) - return ret; - - abis_nm_queue_send_next(bts); - - /* next segment */ - len_remain -= len_to_send; - data += len_to_send; - seq++; - } - return ret; + int len_remain, len_to_send, max_send; + int seq = 0; + int ret; + + len_remain = len; + + while (len_remain) { + struct abis_om_hdr *oh; + struct abis_om_nokia_hdr *noh; + struct msgb *msg = nm_msgb_alloc(); + + if (seq == 0) + max_send = 256 - sizeof(struct abis_om_nokia_hdr); + else + max_send = 256; + + if (len_remain > max_send) { + len_to_send = max_send; + + if (seq == 0) { + /* first segment */ + oh = (struct abis_om_hdr *)msgb_put(msg, + ABIS_OM_NOKIA_HDR_SIZE + + + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */ + oh->sequence = seq; + oh->length = 0; /* 256 bytes */ + + noh = (struct abis_om_nokia_hdr *)oh->data; + + noh->msg_type = msg_type; + noh->spare = 0; + noh->reference = htons(ref); + memcpy(noh->data, data, len_to_send); + } else { + /* segment in between */ + oh = (struct abis_om_hdr *)msgb_put(msg, + sizeof + (struct + abis_om_hdr) + + + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */ + oh->sequence = seq; + oh->length = 0; /* 256 bytes */ + + memcpy(oh->data, data, len_to_send); + } + } else { + + len_to_send = len_remain; + + /* check if message fits in a single segment */ + + if (seq == 0) + return abis_nm_send(bts, msg_type, ref, data, + len_to_send); + + /* last segment */ + + oh = (struct abis_om_hdr *)msgb_put(msg, + sizeof(struct + abis_om_hdr) + + len_to_send); + + oh->mdisc = ABIS_OM_MDISC_FOM; + oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */ + oh->sequence = seq; + oh->length = len_to_send; + + memcpy(oh->data, data, len_to_send); + } + + DEBUGPC(DNM, "Sending multi-segment %d\n", seq); + + ret = abis_nm_sendmsg(bts, msg); + if (ret < 0) + return ret; + + abis_nm_queue_send_next(bts); + + /* next segment */ + len_remain -= len_to_send; + data += len_to_send; + seq++; + } + return ret; } /* TODO: put in a separate file ? */ static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type) { - struct gsm_bts_trx *trx; - uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */ - int len = 0; - int idx = 0; - int ret; - int hopping = 0; - int need_hopping = 0; - - memset(config, 0, sizeof(config)); - - llist_for_each_entry(trx, &bts->trx_list, list) - { -#if 0 /* debugging */ - printf("TRX\n"); - printf(" arfcn: %d\n", trx->arfcn); - printf(" bsic: %d\n", trx->bts->bsic); - uint8_t ca[20]; - memset(ca, 0xFF, sizeof(ca)); - ret = generate_cell_chan_list(ca, trx->bts); - printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca))); - int i; - for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { - struct gsm_bts_trx_ts *ts = &trx->ts[i]; - - printf(" pchan %d: %d\n", i, ts->pchan); - } -#endif - ret = make_fu_config(trx, idx + 1, config + len, &hopping); - need_hopping |= hopping; - len += ret; - - idx++; - } - - ret = make_bts_config(bts_type, idx, config + len, need_hopping); - len += ret; - -#if 0 /* debugging */ - dump_elements(config, len); + struct gsm_bts_trx *trx; + uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */ + int len = 0; + int idx = 0; + int ret; + int hopping = 0; + int need_hopping = 0; + + memset(config, 0, sizeof(config)); + + llist_for_each_entry(trx, &bts->trx_list, list) { +#if 0 /* debugging */ + printf("TRX\n"); + printf(" arfcn: %d\n", trx->arfcn); + printf(" bsic: %d\n", trx->bts->bsic); + uint8_t ca[20]; + memset(ca, 0xFF, sizeof(ca)); + ret = generate_cell_chan_list(ca, trx->bts); + printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca))); + int i; + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + + printf(" pchan %d: %d\n", i, ts->pchan); + } +#endif + ret = make_fu_config(trx, idx + 1, config + len, &hopping); + need_hopping |= hopping; + len += ret; + + idx++; + } + + ret = make_bts_config(bts_type, idx, config + len, need_hopping); + len += ret; + +#if 0 /* debugging */ + dump_elements(config, len); #endif - - return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config, len); + + return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config, + len); } #define GET_NEXT_BYTE if(idx >= len) return 0; \ - ub = data[idx++]; - -static int find_element(uint8_t *data, int len, uint16_t id, uint8_t *value, int max_value) -{ - uint8_t ub; - int idx = 0; - int found = 0; - int constructed; - uint16_t id_value; - - for(;;) { - - GET_NEXT_BYTE; - - /* encoding bit, construced means that other elements are contained */ - constructed = ((ub & 0x20) ? 1 : 0); - - if((ub & 0x1F) == 0x1F) { - /* fixed pattern, ID follows */ - GET_NEXT_BYTE; /* ID */ - id_value = ub & 0x7F; - if(ub & 0x80) { - /* extension bit */ - GET_NEXT_BYTE; /* ID low part */ - id_value = (id_value << 7) | (ub & 0x7F); - } - if(id_value == id) - found = 1; - } - else { - id_value = (ub & 0x3F); - if(id_value == id) - found = 1; - } - - GET_NEXT_BYTE; /* length */ - - if(found) { - /* get data */ - uint8_t n = ub; - uint8_t i; - for(i = 0; i < n; i++) { - GET_NEXT_BYTE; - if(max_value <= 0) - return -1; /* buffer too small */ - *value = ub; - value++; - max_value--; - } - return n; /* length */ - } - else { - /* skip data */ - uint8_t n = ub; - uint8_t i; - for(i = 0; i < n; i++) { - GET_NEXT_BYTE; - } - } - } - return 0; /* not found */ + ub = data[idx++]; + +static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value, + int max_value) +{ + uint8_t ub; + int idx = 0; + int found = 0; + int constructed; + uint16_t id_value; + + for (;;) { + + GET_NEXT_BYTE; + + /* encoding bit, construced means that other elements are contained */ + constructed = ((ub & 0x20) ? 1 : 0); + + if ((ub & 0x1F) == 0x1F) { + /* fixed pattern, ID follows */ + GET_NEXT_BYTE; /* ID */ + id_value = ub & 0x7F; + if (ub & 0x80) { + /* extension bit */ + GET_NEXT_BYTE; /* ID low part */ + id_value = (id_value << 7) | (ub & 0x7F); + } + if (id_value == id) + found = 1; + } else { + id_value = (ub & 0x3F); + if (id_value == id) + found = 1; + } + + GET_NEXT_BYTE; /* length */ + + if (found) { + /* get data */ + uint8_t n = ub; + uint8_t i; + for (i = 0; i < n; i++) { + GET_NEXT_BYTE; + if (max_value <= 0) + return -1; /* buffer too small */ + *value = ub; + value++; + max_value--; + } + return n; /* length */ + } else { + /* skip data */ + uint8_t n = ub; + uint8_t i; + for (i = 0; i < n; i++) { + GET_NEXT_BYTE; + } + } + } + return 0; /* not found */ } -static int dump_elements(uint8_t *data, int len) -{ - uint8_t ub; - int idx = 0; - int constructed; - uint16_t id_value; - static char indent[100] = ""; /* TODO: move static to BTS context */ - - for(;;) { - - GET_NEXT_BYTE; - - /* encoding bit, construced means that other elements are contained */ - constructed = ((ub & 0x20) ? 1 : 0); - - if((ub & 0x1F) == 0x1F) { - /* fixed pattern, ID follows */ - GET_NEXT_BYTE; /* ID */ - id_value = ub & 0x7F; - if(ub & 0x80) { - /* extension bit */ - GET_NEXT_BYTE; /* ID low part */ - id_value = (id_value << 7) | (ub & 0x7F); - } - - } - else { - id_value = (ub & 0x3F); - } - - GET_NEXT_BYTE; /* length */ - - printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value, get_element_name_string(id_value), constructed ? "** constructed **" : ""); - printf("%s length = %d\n", indent, ub); - printf("%s %s\n", indent, osmo_hexdump(data + idx, ub)); - - if(constructed) { - int indent_len = strlen(indent); - strcat(indent, " "); - - dump_elements(data + idx, ub); - - indent[indent_len] = 0; - } - /* skip data */ - uint8_t n = ub; - uint8_t i; - for(i = 0; i < n; i++) { - GET_NEXT_BYTE; - } - } - return 0; +static int dump_elements(uint8_t * data, int len) +{ + uint8_t ub; + int idx = 0; + int constructed; + uint16_t id_value; + static char indent[100] = ""; /* TODO: move static to BTS context */ + + for (;;) { + + GET_NEXT_BYTE; + + /* encoding bit, construced means that other elements are contained */ + constructed = ((ub & 0x20) ? 1 : 0); + + if ((ub & 0x1F) == 0x1F) { + /* fixed pattern, ID follows */ + GET_NEXT_BYTE; /* ID */ + id_value = ub & 0x7F; + if (ub & 0x80) { + /* extension bit */ + GET_NEXT_BYTE; /* ID low part */ + id_value = (id_value << 7) | (ub & 0x7F); + } + + } else { + id_value = (ub & 0x3F); + } + + GET_NEXT_BYTE; /* length */ + + printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value, + get_element_name_string(id_value), + constructed ? "** constructed **" : ""); + printf("%s length = %d\n", indent, ub); + printf("%s %s\n", indent, osmo_hexdump(data + idx, ub)); + + if (constructed) { + int indent_len = strlen(indent); + strcat(indent, " "); + + dump_elements(data + idx, ub); + + indent[indent_len] = 0; + } + /* skip data */ + uint8_t n = ub; + uint8_t i; + for (i = 0; i < n; i++) { + GET_NEXT_BYTE; + } + } + return 0; } /* TODO: put in a separate file ? */ @@ -1652,19 +1663,19 @@ static int dump_elements(uint8_t *data, int len) static void abis_nm_queue_send_next(struct gsm_bts *bts) { - int wait = 0; - struct msgb *msg; - /* the queue is empty */ - while (!llist_empty(&bts->abis_queue)) { - msg = msgb_dequeue(&bts->abis_queue); - wait = OBSC_NM_W_ACK_CB(msg); - _abis_nm_sendmsg(msg, 0); - - if (wait) - break; - } - - bts->abis_nm_pend = wait; + int wait = 0; + struct msgb *msg; + /* the queue is empty */ + while (!llist_empty(&bts->abis_queue)) { + msg = msgb_dequeue(&bts->abis_queue); + wait = OBSC_NM_W_ACK_CB(msg); + _abis_nm_sendmsg(msg, 0); + + if (wait) + break; + } + + bts->abis_nm_pend = wait; } /* TODO: put in a separate file ? */ @@ -1673,22 +1684,22 @@ static void abis_nm_queue_send_next(struct gsm_bts *bts) static void reset_timer_cb(void *_bts) { - struct gsm_bts *bts = _bts; - struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; - struct e1inp_line *line; - - wait_reset = 0; - - /* OML link */ - line = e1inp_line_get(e1_link->e1_nr); - if (!line) { - LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to " - "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); - return; - } - - start_sabm_in_line(line, 0, -1); /* stop all first */ - start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */ + struct gsm_bts *bts = _bts; + struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; + struct e1inp_line *line; + + wait_reset = 0; + + /* OML link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to " + "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); + return; + } + + start_sabm_in_line(line, 0, -1); /* stop all first */ + start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */ } /* TODO: put in a separate file ? */ @@ -1716,234 +1727,256 @@ static void reset_timer_cb(void *_bts) static int abis_nm_rcvmsg_fom(struct msgb *mb) { - struct gsm_bts *bts = mb->trx->bts; - struct abis_om_hdr *oh = msgb_l2(mb); - struct abis_om_nokia_hdr *noh = msgb_l3(mb); - uint8_t mt = noh->msg_type; - int ret = 0; - uint16_t ref = ntohs(noh->reference); - /* TODO: move statics to BTS context */ - static int conf = 0; - static uint8_t bts_type = 0xFF; - uint8_t info[256]; - uint8_t ack = 0xFF; - uint8_t severity = 0xFF; - int str_len; - int len_data; - - if(wait_reset) { - LOGP(DNM, LOGL_INFO, "Ignore message while waiting for reset\n"); - return ret; - } - - if(oh->length < sizeof(struct abis_om_nokia_hdr)) { - LOGP(DNM, LOGL_ERROR, "Message too short\n"); - return -EINVAL; - } - - len_data = oh->length - sizeof(struct abis_om_nokia_hdr); - LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt)); -#if 0 /* debugging */ - dump_elements(noh->data, len_data); + struct gsm_bts *bts = mb->trx->bts; + struct abis_om_hdr *oh = msgb_l2(mb); + struct abis_om_nokia_hdr *noh = msgb_l3(mb); + uint8_t mt = noh->msg_type; + int ret = 0; + uint16_t ref = ntohs(noh->reference); + /* TODO: move statics to BTS context */ + static int conf = 0; + static uint8_t bts_type = 0xFF; + uint8_t info[256]; + uint8_t ack = 0xFF; + uint8_t severity = 0xFF; + int str_len; + int len_data; + + if (wait_reset) { + LOGP(DNM, LOGL_INFO, + "Ignore message while waiting for reset\n"); + return ret; + } + + if (oh->length < sizeof(struct abis_om_nokia_hdr)) { + LOGP(DNM, LOGL_ERROR, "Message too short\n"); + return -EINVAL; + } + + len_data = oh->length - sizeof(struct abis_om_nokia_hdr); + LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt)); +#if 0 /* debugging */ + dump_elements(noh->data, len_data); #endif - - switch (mt) { - case NOKIA_MSG_OMU_STARTED: - if(find_element(noh->data, len_data, NOKIA_EI_BTS_TYPE, &bts_type, sizeof(uint8_t)) == sizeof(uint8_t)) - LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", bts_type, get_bts_type_string(bts_type)); - else - LOGP(DNM, LOGL_ERROR, "BTS type not found\n"); - /* send START_DOWNLOAD_REQ */ - abis_nm_download_req(bts, ref); - break; - case NOKIA_MSG_MF_REQ: - break; - case NOKIA_MSG_CONF_REQ: - /* send ACK */ - abis_nm_ack(bts, ref); - abis_nm_queue_send_next(bts); - /* send CONF_DATA */ - abis_nm_send_config(bts, bts_type); - conf = 1; - break; - case NOKIA_MSG_ACK: - if(find_element(noh->data, len_data, NOKIA_EI_ACK, &ack, sizeof(uint8_t)) == sizeof(uint8_t)) { - LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack); - if(ack != 1) { - LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n", ack); - /* TODO: properly handle failures (NACK) */ - } - } - else - LOGP(DNM, LOGL_ERROR, "ACK not found\n"); - - /* TODO: the assumption for the following is that no NACK was received */ - - /* ACK for reset message ? */ - if(do_reset != 0) { - do_reset = 0; - - /* - TODO: For the InSite processing the received data is - blocked in the driver during reset. - Otherwise the LAPD module might assert because the InSite - sends garbage on the E1 line during reset. - This is done by looking at "wait_reset" in the driver - (function handle_ts1_read()) and ignoring the received data. - It seems to be necessary for the MetroSite too. - */ - wait_reset = 1; - - reset_timer.cb = &reset_timer_cb; - reset_timer.data = bts; - osmo_timer_schedule(&reset_timer, RESET_INTERVAL); - - struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; - struct e1inp_line *line; - /* OML link */ - line = e1inp_line_get(e1_link->e1_nr); - if (!line) { - LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to " - "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); - return -ENOMEM; - } - - start_sabm_in_line(line, 0, -1); /* stop all first */ - } - - /* ACK for CONF DATA message ? */ - if(conf != 0) { - /* start TRX (RSL link) */ - - struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link; - struct e1inp_line *line; - - conf = 0; - - /* RSL Link */ - line = e1inp_line_get(e1_link->e1_nr); - if (!line) { - LOGP(DINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring " - "to non-existing E1 line %u\n", mb->trx->bts->nr, - mb->trx->nr, e1_link->e1_nr); - return -ENOMEM; - } - /* start TRX */ - start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */ - } - break; - case NOKIA_MSG_STATE_CHANGED: - /* send ACK */ - abis_nm_ack(bts, ref); - break; - case NOKIA_MSG_CONF_COMPLETE: - /* send ACK */ - abis_nm_ack(bts, ref); - break; - case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */ - /* send ACK (do we have to send an ACK ?) */ - abis_nm_ack(bts, ref); - break; - case NOKIA_MSG_ALARM: - find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity, sizeof(severity)); - /* TODO: there might be alarms with both elements set */ - str_len = find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info, sizeof(info)); - if(str_len > 0) { - info[str_len] = 0; - LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n", get_severity_string(severity), severity, info); - } else { /* nothing found, try details */ - str_len = find_element(noh->data, len_data, NOKIA_EI_ALARM_DETAIL, info, sizeof(info)); - if(str_len > 0) { - uint16_t code; - info[str_len] = 0; - code = (info[0] << 8) + info[1]; - LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d), code 0x%X : %s\n", get_severity_string(severity), severity, code, info + 2); - } - } - /* send ACK */ - abis_nm_ack(bts, ref); - break; - } - - abis_nm_queue_send_next(bts); - - return ret; + + switch (mt) { + case NOKIA_MSG_OMU_STARTED: + if (find_element + (noh->data, len_data, NOKIA_EI_BTS_TYPE, &bts_type, + sizeof(uint8_t)) == sizeof(uint8_t)) + LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", bts_type, + get_bts_type_string(bts_type)); + else + LOGP(DNM, LOGL_ERROR, "BTS type not found\n"); + /* send START_DOWNLOAD_REQ */ + abis_nm_download_req(bts, ref); + break; + case NOKIA_MSG_MF_REQ: + break; + case NOKIA_MSG_CONF_REQ: + /* send ACK */ + abis_nm_ack(bts, ref); + abis_nm_queue_send_next(bts); + /* send CONF_DATA */ + abis_nm_send_config(bts, bts_type); + conf = 1; + break; + case NOKIA_MSG_ACK: + if (find_element + (noh->data, len_data, NOKIA_EI_ACK, &ack, + sizeof(uint8_t)) == sizeof(uint8_t)) { + LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack); + if (ack != 1) { + LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n", + ack); + /* TODO: properly handle failures (NACK) */ + } + } else + LOGP(DNM, LOGL_ERROR, "ACK not found\n"); + + /* TODO: the assumption for the following is that no NACK was received */ + + /* ACK for reset message ? */ + if (do_reset != 0) { + do_reset = 0; + + /* + TODO: For the InSite processing the received data is + blocked in the driver during reset. + Otherwise the LAPD module might assert because the InSite + sends garbage on the E1 line during reset. + This is done by looking at "wait_reset" in the driver + (function handle_ts1_read()) and ignoring the received data. + It seems to be necessary for the MetroSite too. + */ + wait_reset = 1; + + reset_timer.cb = &reset_timer_cb; + reset_timer.data = bts; + osmo_timer_schedule(&reset_timer, RESET_INTERVAL); + + struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; + struct e1inp_line *line; + /* OML link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, + "BTS %u OML link referring to " + "non-existing E1 line %u\n", bts->nr, + e1_link->e1_nr); + return -ENOMEM; + } + + start_sabm_in_line(line, 0, -1); /* stop all first */ + } + + /* ACK for CONF DATA message ? */ + if (conf != 0) { + /* start TRX (RSL link) */ + + struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link; + struct e1inp_line *line; + + conf = 0; + + /* RSL Link */ + line = e1inp_line_get(e1_link->e1_nr); + if (!line) { + LOGP(DINP, LOGL_ERROR, + "TRX (%u/%u) RSL link referring " + "to non-existing E1 line %u\n", + mb->trx->bts->nr, mb->trx->nr, + e1_link->e1_nr); + return -ENOMEM; + } + /* start TRX */ + start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */ + } + break; + case NOKIA_MSG_STATE_CHANGED: + /* send ACK */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_CONF_COMPLETE: + /* send ACK */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */ + /* send ACK (do we have to send an ACK ?) */ + abis_nm_ack(bts, ref); + break; + case NOKIA_MSG_ALARM: + find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity, + sizeof(severity)); + /* TODO: there might be alarms with both elements set */ + str_len = + find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info, + sizeof(info)); + if (str_len > 0) { + info[str_len] = 0; + LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n", + get_severity_string(severity), severity, info); + } else { /* nothing found, try details */ + str_len = + find_element(noh->data, len_data, + NOKIA_EI_ALARM_DETAIL, info, + sizeof(info)); + if (str_len > 0) { + uint16_t code; + info[str_len] = 0; + code = (info[0] << 8) + info[1]; + LOGP(DNM, LOGL_INFO, + "ALARM Severity %s (%d), code 0x%X : %s\n", + get_severity_string(severity), severity, + code, info + 2); + } + } + /* send ACK */ + abis_nm_ack(bts, ref); + break; + } + + abis_nm_queue_send_next(bts); + + return ret; } /* TODO: put in a separate file ? */ int abis_nokia_rcvmsg(struct msgb *msg) { - struct abis_om_hdr *oh = msgb_l2(msg); - int rc = 0; - - /* Various consistency checks */ - if (oh->placement != ABIS_OM_PLACEMENT_ONLY) { - LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n", - oh->placement); - if (oh->placement != ABIS_OM_PLACEMENT_FIRST) - return -EINVAL; - } - if (oh->sequence != 0) { - LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n", - oh->sequence); - return -EINVAL; - } - msg->l3h = (unsigned char *)oh + sizeof(*oh); - - switch (oh->mdisc) { - case ABIS_OM_MDISC_FOM: - LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n"); - rc = abis_nm_rcvmsg_fom(msg); - break; - case ABIS_OM_MDISC_MANUF: - LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n"); - break; - case ABIS_OM_MDISC_MMI: - case ABIS_OM_MDISC_TRAU: - LOGP(DNM, LOGL_ERROR, "unimplemented ABIS OML message discriminator 0x%x\n", - oh->mdisc); - break; - default: - LOGP(DNM, LOGL_ERROR, "unknown ABIS OML message discriminator 0x%x\n", - oh->mdisc); - return -EINVAL; - } - - msgb_free(msg); - return rc; + struct abis_om_hdr *oh = msgb_l2(msg); + int rc = 0; + + /* Various consistency checks */ + if (oh->placement != ABIS_OM_PLACEMENT_ONLY) { + LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n", + oh->placement); + if (oh->placement != ABIS_OM_PLACEMENT_FIRST) + return -EINVAL; + } + if (oh->sequence != 0) { + LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n", + oh->sequence); + return -EINVAL; + } + msg->l3h = (unsigned char *)oh + sizeof(*oh); + + switch (oh->mdisc) { + case ABIS_OM_MDISC_FOM: + LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n"); + rc = abis_nm_rcvmsg_fom(msg); + break; + case ABIS_OM_MDISC_MANUF: + LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n"); + break; + case ABIS_OM_MDISC_MMI: + case ABIS_OM_MDISC_TRAU: + LOGP(DNM, LOGL_ERROR, + "unimplemented ABIS OML message discriminator 0x%x\n", + oh->mdisc); + break; + default: + LOGP(DNM, LOGL_ERROR, + "unknown ABIS OML message discriminator 0x%x\n", + oh->mdisc); + return -EINVAL; + } + + msgb_free(msg); + return rc; } static int bts_model_nokia_site_start(struct gsm_network *net); static struct gsm_bts_model model_nokia_site = { - .type = GSM_BTS_TYPE_NOKIA_SITE, - .name = "nokia_site", - .start = bts_model_nokia_site_start, - .oml_rcvmsg = &abis_nokia_rcvmsg + .type = GSM_BTS_TYPE_NOKIA_SITE, + .name = "nokia_site", + .start = bts_model_nokia_site_start, + .oml_rcvmsg = &abis_nokia_rcvmsg }; static struct gsm_network *my_net; static int bts_model_nokia_site_start(struct gsm_network *net) { - model_nokia_site.features.data = &model_nokia_site._features_data[0]; - model_nokia_site.features.data_len = sizeof(model_nokia_site._features_data); + model_nokia_site.features.data = &model_nokia_site._features_data[0]; + model_nokia_site.features.data_len = + sizeof(model_nokia_site._features_data); + + gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING); + gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD); - gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING); - gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD); + osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL); + osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL); + osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); - osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL); - osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL); - osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); + my_net = net; - my_net = net; - - return 0; + return 0; } int bts_model_nokia_site_init(void) { - return gsm_bts_model_register(&model_nokia_site); + return gsm_bts_model_register(&model_nokia_site); } - -- cgit v1.2.3 From cde579473b6e38c3f0aee0365e8eb2cc95cace1d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:13:46 +0200 Subject: NOKIA: Some more whitespace changes --- openbsc/src/libbsc/bts_nokia_site.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 033f6fec7..64b016720 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -81,12 +81,12 @@ static int shutdown_om(struct gsm_bts *bts) #define SAPI_OML 62 #define SAPI_RSL 0 -/* +/* Tell LAPD to start start the SAP (send SABM requests) for all signalling - timeslots in this line - - Attention: this has to be adapted for MISDN + timeslots in this line + + Attention: this has to be adapted for mISDN */ static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) @@ -929,7 +929,7 @@ static uint8_t fu_config_template[] = { /* TODO: put in a separate file ? */ /* - build the configuration for each TRX + build the configuration for each TRX */ static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, @@ -977,11 +977,11 @@ static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, /* set BSIC */ - /* + /* Attention: all TRX except the first one seem to get the TSC from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION, - GSM 04.08 CHANNEL DESCRIPTION). - There was a bug in rsl_chan_activate_lchan() setting this parameter. + GSM 04.08 CHANNEL DESCRIPTION). + There was a bug in rsl_chan_activate_lchan() setting this parameter. */ uint8_t bsic = trx->bts->bsic; @@ -1012,8 +1012,8 @@ static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id, 7 = E-RACH (Talk family) 9 = Dual rate (capability for TCH/F and TCH/H) 10 = reserved for BTS internal use - 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (This channel configuration type can be used in GPRS release 2). - 0xFF = spare TS + 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2). + 0xFF = spare TS */ if (ts->pchan == GSM_PCHAN_NONE) @@ -1218,9 +1218,7 @@ void set_real_time(uint8_t * real_time) /* TODO: put in a separate file ? */ /* - build the configuration data - */ static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config, @@ -1706,21 +1704,14 @@ static void reset_timer_cb(void *_bts) /* This is how the configuration is done: - - start OML link - - reset BTS - - receive ACK, wait some time and restart OML link - - receive OMU STARTED message, send START DOWNLOAD REQ - - receive CNF REQ message, send CONF DATA - - receive ACK, start RSL link(s) - ACK some other messages received from the BTS. - + Probably its also possible to configure the BTS without a reset, this has not been tested yet. */ -- cgit v1.2.3 From 9d2f377927856a55c5e8e1077f82de40723acdbd Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:19:06 +0200 Subject: NOKIA: move 'conf' and 'bts_type' into 'struct gsm_bts' This is one step in the direction of supporting multiple Nokia BTS --- openbsc/src/libbsc/bts_nokia_site.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 64b016720..6cafaae1c 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -1724,9 +1724,6 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) uint8_t mt = noh->msg_type; int ret = 0; uint16_t ref = ntohs(noh->reference); - /* TODO: move statics to BTS context */ - static int conf = 0; - static uint8_t bts_type = 0xFF; uint8_t info[256]; uint8_t ack = 0xFF; uint8_t severity = 0xFF; @@ -1752,11 +1749,12 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) switch (mt) { case NOKIA_MSG_OMU_STARTED: - if (find_element - (noh->data, len_data, NOKIA_EI_BTS_TYPE, &bts_type, - sizeof(uint8_t)) == sizeof(uint8_t)) - LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", bts_type, - get_bts_type_string(bts_type)); + if (find_element(noh->data, len_data, + NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type, + sizeof(uint8_t)) == sizeof(uint8_t)) + LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", + bts->nokia.bts_type, + get_bts_type_string(bts->nokia.bts_type)); else LOGP(DNM, LOGL_ERROR, "BTS type not found\n"); /* send START_DOWNLOAD_REQ */ @@ -1769,8 +1767,8 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) abis_nm_ack(bts, ref); abis_nm_queue_send_next(bts); /* send CONF_DATA */ - abis_nm_send_config(bts, bts_type); - conf = 1; + abis_nm_send_config(bts, bts->nokia.bts_type); + bts->nokia.configured = 1; break; case NOKIA_MSG_ACK: if (find_element @@ -1822,13 +1820,13 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) } /* ACK for CONF DATA message ? */ - if (conf != 0) { + if (bts->nokia.configured != 0) { /* start TRX (RSL link) */ struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link; struct e1inp_line *line; - conf = 0; + bts->nokia.configured = 0; /* RSL Link */ line = e1inp_line_get(e1_link->e1_nr); -- cgit v1.2.3 From c8755af8a526dbc95e31fa38547bc42a10f44971 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:22:17 +0200 Subject: NOKIA: Move more static variables into 'struct gsm_bts' --- openbsc/include/openbsc/gsm_data_shared.h | 7 +++++++ openbsc/src/libbsc/bts_nokia_site.c | 23 +++++++++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index b9829222f..e3ab5f483 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -488,6 +488,13 @@ struct gsm_bts { struct { unsigned long serno; } hsl; + struct { + uint8_t bts_type; + int configured:1, + do_reset:1, + wait_reset:1; + struct osmo_timer_list reset_timer; + } nokia; }; /* Not entirely sure how ip.access specific this is */ diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 6cafaae1c..30e590043 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -42,11 +42,6 @@ /* TODO: put in a separate file ? */ -/* TODO: move statics to BTS context */ -static int do_reset = 1; -/*static*/ int wait_reset = 0; -struct osmo_timer_list reset_timer; /* timer to re-start after reset */ - #define RESET_INTERVAL 0, 3000000 /* 3 seconds */ extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg); @@ -62,7 +57,7 @@ static void bootstrap_om_bts(struct gsm_bts *bts) { LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); - if (do_reset) + if (bts->nokia.do_reset) abis_nm_reset(bts, 1); } @@ -1686,7 +1681,7 @@ static void reset_timer_cb(void *_bts) struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; struct e1inp_line *line; - wait_reset = 0; + bts->nokia.wait_reset = 0; /* OML link */ line = e1inp_line_get(e1_link->e1_nr); @@ -1730,7 +1725,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) int str_len; int len_data; - if (wait_reset) { + if (bts->nokia.wait_reset) { LOGP(DNM, LOGL_INFO, "Ignore message while waiting for reset\n"); return ret; @@ -1786,8 +1781,8 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) /* TODO: the assumption for the following is that no NACK was received */ /* ACK for reset message ? */ - if (do_reset != 0) { - do_reset = 0; + if (bts->nokia.do_reset != 0) { + bts->nokia.do_reset = 0; /* TODO: For the InSite processing the received data is @@ -1798,11 +1793,11 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) (function handle_ts1_read()) and ignoring the received data. It seems to be necessary for the MetroSite too. */ - wait_reset = 1; + bts->nokia.wait_reset = 1; - reset_timer.cb = &reset_timer_cb; - reset_timer.data = bts; - osmo_timer_schedule(&reset_timer, RESET_INTERVAL); + bts->nokia.reset_timer.cb = &reset_timer_cb; + bts->nokia.reset_timer.data = bts; + osmo_timer_schedule(&bts->nokia.reset_timer, RESET_INTERVAL); struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; struct e1inp_line *line; -- cgit v1.2.3 From 3c3003f703e77af2b80ea5f1e019ab77e658c5ec Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:28:20 +0200 Subject: NOKIA: use 'value_string' for severity and bts_type --- openbsc/src/libbsc/bts_nokia_site.c | 79 +++++++++++++++---------------------- 1 file changed, 31 insertions(+), 48 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 30e590043..281e8cee7 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -672,58 +672,41 @@ static char *get_element_name_string(uint16_t element) } } -static char *get_bts_type_string(uint8_t type) +static const struct value_string nokia_bts_types[] = { + { 0x0a, "MetroSite GSM 900" }, + { 0x0b, "MetroSite GSM 1800" }, + { 0x0c, "MetroSite GSM 1900 (PCS)" }, + { 0x0d, "MetroSite GSM 900 & 1800" }, + { 0x0e, "InSite GSM 900" }, + { 0x0f, "InSite GSM 1800" }, + { 0x10, "InSite GSM 1900" }, + { 0x11, "UltraSite GSM 900" }, + { 0x12, "UltraSite GSM 1800" }, + { 0x13, "UltraSite GSM/US-TDMA 1900" }, + { 0x14, "UltraSite GSM 900 & 1800" }, + { 0x16, "UltraSite GSM/US-TDMA 850" }, + { 0x18, "MetroSite GSM/US-TDMA 850" }, + { 0x19, "UltraSite GSM 800/1900" }, + { 0, NULL } +}; + +static const char *get_bts_type_string(uint8_t type) { - switch (type) { - case 0x0A: - return "MetroSite GSM 900"; - case 0x0B: - return "MetroSite GSM 1800"; - case 0x0C: - return "MetroSite GSM 1900 (PCS)"; - case 0x0D: - return "MetroSite GSM 900 & 1800"; - case 0x0E: - return "InSite GSM 900"; - case 0x0F: - return "InSite GSM 1800"; - case 0x10: - return "InSite GSM 1900"; - case 0x11: - return "UltraSite GSM 900"; - case 0x12: - return "UltraSite GSM 1800"; - case 0x13: - return "UltraSite GSM/US-TDMA 1900"; - case 0x14: - return "UltraSite GSM 900 & 1800"; - case 0x16: - return "UltraSite GSM/US-TDMA 850"; - case 0x18: - return "MetroSite GSM/US-TDMA 850"; - case 0x19: - return "UltraSite GSM 800/1900"; - default: - return "unknown"; - } + return get_value_string(nokia_bts_types, type); } -static char *get_severity_string(uint8_t severity) +static const struct value_string nokia_severity[] = { + { 0, "indeterminate" }, + { 1, "critical" }, + { 2, "major" }, + { 3, "minor" }, + { 4, "warning" }, + { 0, NULL } +}; + +static const char *get_severity_string(uint8_t severity) { - switch (severity) { - case 0: - return "indeterminate"; - case 1: - return "critical"; - case 2: - return "major"; - case 3: - return "minor"; - case 4: - return "warning"; - default: - return "unknown"; - } + return get_value_string(nokia_severity, severity); } /* TODO: put in a separate file ? */ -- cgit v1.2.3 From 44d26113bcf74cbbce7d8a4139731fd8880f6873 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 28 Jul 2011 00:43:13 +0200 Subject: NOKIA: use 'struct value_string' whenever possible --- openbsc/src/libbsc/bts_nokia_site.c | 715 ++++++++++++------------------------ 1 file changed, 243 insertions(+), 472 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 281e8cee7..6d14bddaf 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -194,482 +194,253 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, /* TODO: put in a separate file ? */ -static char *get_msg_type_name_string(uint8_t msg_type) +static const struct value_string nokia_msgt_name[] = { + { 0x80, "NOKIA_BTS_CONF_DATA" }, + { 0x81, "NOKIA_BTS_ACK" }, + { 0x82, "NOKIA_BTS_OMU_STARTED" }, + { 0x83, "NOKIA_BTS_START_DOWNLOAD_REQ" }, + { 0x84, "NOKIA_BTS_MF_REQ" }, + { 0x85, "NOKIA_BTS_AF_REQ" }, + { 0x86, "NOKIA_BTS_RESET_REQ" }, + { 0x87, "NOKIA_reserved" }, + { 0x88, "NOKIA_BTS_CONF_REQ" }, + { 0x89, "NOKIA_BTS_TEST_REQ" }, + { 0x8A, "NOKIA_BTS_TEST_REPORT" }, + { 0x8B, "NOKIA_reserved" }, + { 0x8C, "NOKIA_reserved" }, + { 0x8D, "NOKIA_reserved" }, + { 0x8E, "NOKIA_BTS_CONF_COMPL" }, + { 0x8F, "NOKIA_reserved" }, + { 0x90, "NOKIA_BTS_STM_TEST_REQ" }, + { 0x91, "NOKIA_BTS_STM_TEST_REPORT" }, + { 0x92, "NOKIA_BTS_TRANSMISSION_COMMAND" }, + { 0x93, "NOKIA_BTS_TRANSMISSION_ANSWER" }, + { 0x94, "NOKIA_BTS_HW_DB_UPLOAD_REQ" }, + { 0x95, "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ" }, + { 0x96, "NOKIA_BTS_HW_DB_SAVE_REQ" }, + { 0x97, "NOKIA_BTS_FLASH_ERASURE_REQ" }, + { 0x98, "NOKIA_BTS_HW_DB_DOWNLOAD_REQ" }, + { 0x99, "NOKIA_BTS_PWR_SUPPLY_CONTROL" }, + { 0x9A, "NOKIA_BTS_ATTRIBUTE_REQ" }, + { 0x9B, "NOKIA_BTS_ATTRIBUTE_REPORT" }, + { 0x9C, "NOKIA_BTS_HW_REQ" }, + { 0x9D, "NOKIA_BTS_HW_REPORT" }, + { 0x9E, "NOKIA_BTS_RTE_TEST_REQ" }, + { 0x9F, "NOKIA_BTS_RTE_TEST_REPORT" }, + { 0xA0, "NOKIA_BTS_HW_DB_VERIFICATION_REQ" }, + { 0xA1, "NOKIA_BTS_CLOCK_REQ" }, + { 0xA2, "NOKIA_AC_CIRCUIT_REQ_NACK" }, + { 0xA3, "NOKIA_AC_INTERRUPTED" }, + { 0xA4, "NOKIA_BTS_NEW_TRE_INFO" }, + { 0xA5, "NOKIA_AC_BSC_CIRCUITS_ALLOCATED" }, + { 0xA6, "NOKIA_BTS_TRE_POLL_LIST" }, + { 0xA7, "NOKIA_AC_CIRCUIT_REQ" }, + { 0xA8, "NOKIA_BTS_BLOCK_CTRL_REQ" }, + { 0xA9, "NOKIA_BTS_GSM_TIME_REQ" }, + { 0xAA, "NOKIA_BTS_GSM_TIME" }, + { 0xAB, "NOKIA_BTS_OUTPUT_CONTROL" }, + { 0xAC, "NOKIA_BTS_STATE_CHANGED" }, + { 0xAD, "NOKIA_BTS_SW_SAVE_REQ" }, + { 0xAE, "NOKIA_BTS_ALARM" }, + { 0xAF, "NOKIA_BTS_CHA_ADM_STATE" }, + { 0xB0, "NOKIA_AC_POOL_SIZE_REPORT" }, + { 0xB1, "NOKIA_AC_POOL_SIZE_INQUIRY" }, + { 0xB2, "NOKIA_BTS_COMMISS_TEST_COMPLETED" }, + { 0xB3, "NOKIA_BTS_COMMISS_TEST_REQ" }, + { 0xB4, "NOKIA_BTS_TRANSP_BTS_TO_BSC" }, + { 0xB5, "NOKIA_BTS_TRANSP_BSC_TO_BTS" }, + { 0xB6, "NOKIA_BTS_LCS_COMMAND" }, + { 0xB7, "NOKIA_BTS_LCS_ANSWER" }, + { 0xB8, "NOKIA_BTS_LMU_FN_OFFSET_COMMAND" }, + { 0xB9, "NOKIA_BTS_LMU_FN_OFFSET_ANSWER" }, + { 0, NULL } +}; + +static const char *get_msg_type_name_string(uint8_t msg_type) { - switch (msg_type) { - case 0x80: - return "NOKIA_BTS_CONF_DATA"; - case 0x81: - return "NOKIA_BTS_ACK"; - case 0x82: - return "NOKIA_BTS_OMU_STARTED"; - case 0x83: - return "NOKIA_BTS_START_DOWNLOAD_REQ"; - case 0x84: - return "NOKIA_BTS_MF_REQ"; - case 0x85: - return "NOKIA_BTS_AF_REQ"; - case 0x86: - return "NOKIA_BTS_RESET_REQ"; - case 0x87: - return "NOKIA_reserved"; - case 0x88: - return "NOKIA_BTS_CONF_REQ"; - case 0x89: - return "NOKIA_BTS_TEST_REQ"; - case 0x8A: - return "NOKIA_BTS_TEST_REPORT"; - case 0x8B: - return "NOKIA_reserved"; - case 0x8C: - return "NOKIA_reserved"; - case 0x8D: - return "NOKIA_reserved"; - case 0x8E: - return "NOKIA_BTS_CONF_COMPL"; - case 0x8F: - return "NOKIA_reserved"; - case 0x90: - return "NOKIA_BTS_STM_TEST_REQ"; - case 0x91: - return "NOKIA_BTS_STM_TEST_REPORT"; - case 0x92: - return "NOKIA_BTS_TRANSMISSION_COMMAND"; - case 0x93: - return "NOKIA_BTS_TRANSMISSION_ANSWER"; - case 0x94: - return "NOKIA_BTS_HW_DB_UPLOAD_REQ"; - case 0x95: - return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ"; - case 0x96: - return "NOKIA_BTS_HW_DB_SAVE_REQ"; - case 0x97: - return "NOKIA_BTS_FLASH_ERASURE_REQ"; - case 0x98: - return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ"; - case 0x99: - return "NOKIA_BTS_PWR_SUPPLY_CONTROL"; - case 0x9A: - return "NOKIA_BTS_ATTRIBUTE_REQ"; - case 0x9B: - return "NOKIA_BTS_ATTRIBUTE_REPORT"; - case 0x9C: - return "NOKIA_BTS_HW_REQ"; - case 0x9D: - return "NOKIA_BTS_HW_REPORT"; - case 0x9E: - return "NOKIA_BTS_RTE_TEST_REQ"; - case 0x9F: - return "NOKIA_BTS_RTE_TEST_REPORT"; - case 0xA0: - return "NOKIA_BTS_HW_DB_VERIFICATION_REQ"; - case 0xA1: - return "NOKIA_BTS_CLOCK_REQ"; - case 0xA2: - return "NOKIA_AC_CIRCUIT_REQ_NACK"; - case 0xA3: - return "NOKIA_AC_INTERRUPTED"; - case 0xA4: - return "NOKIA_BTS_NEW_TRE_INFO"; - case 0xA5: - return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED"; - case 0xA6: - return "NOKIA_BTS_TRE_POLL_LIST"; - case 0xA7: - return "NOKIA_AC_CIRCUIT_REQ"; - case 0xA8: - return "NOKIA_BTS_BLOCK_CTRL_REQ"; - case 0xA9: - return "NOKIA_BTS_GSM_TIME_REQ"; - case 0xAA: - return "NOKIA_BTS_GSM_TIME"; - case 0xAB: - return "NOKIA_BTS_OUTPUT_CONTROL"; - case 0xAC: - return "NOKIA_BTS_STATE_CHANGED"; - case 0xAD: - return "NOKIA_BTS_SW_SAVE_REQ"; - case 0xAE: - return "NOKIA_BTS_ALARM"; - case 0xAF: - return "NOKIA_BTS_CHA_ADM_STATE"; - case 0xB0: - return "NOKIA_AC_POOL_SIZE_REPORT"; - case 0xB1: - return "NOKIA_AC_POOL_SIZE_INQUIRY"; - case 0xB2: - return "NOKIA_BTS_COMMISS_TEST_COMPLETED"; - case 0xB3: - return "NOKIA_BTS_COMMISS_TEST_REQ"; - case 0xB4: - return "NOKIA_BTS_TRANSP_BTS_TO_BSC"; - case 0xB5: - return "NOKIA_BTS_TRANSP_BSC_TO_BTS"; - case 0xB6: - return "NOKIA_BTS_LCS_COMMAND"; - case 0xB7: - return "NOKIA_BTS_LCS_ANSWER"; - case 0xB8: - return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND"; - case 0xB9: - return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER"; - default: - return "unknown"; - } + return get_value_string(nokia_msgt_name, msg_type); } -static char *get_element_name_string(uint16_t element) +static const struct value_string nokia_element_name[] = { + { 0x01, "Ny1" }, + { 0x02, "T3105_F" }, + { 0x03, "Interference band limits" }, + { 0x04, "Interference report timer in secs" }, + { 0x05, "Channel configuration per TS" }, + { 0x06, "BSIC" }, + { 0x07, "RACH report timer in secs" }, + { 0x08, "Hardware database status" }, + { 0x09, "BTS RX level" }, + { 0x0A, "ARFN" }, + { 0x0B, "STM antenna attenuation" }, + { 0x0C, "Cell allocation bitmap" }, + { 0x0D, "Radio definition per TS" }, + { 0x0E, "Frame number" }, + { 0x0F, "Antenna diversity" }, + { 0x10, "T3105_D" }, + { 0x11, "File format" }, + { 0x12, "Last File" }, + { 0x13, "BTS type" }, + { 0x14, "Erasure mode" }, + { 0x15, "Hopping mode" }, + { 0x16, "Floating TRX" }, + { 0x17, "Power supplies" }, + { 0x18, "Reset type" }, + { 0x19, "Averaging period" }, + { 0x1A, "RBER2" }, + { 0x1B, "LAC" }, + { 0x1C, "CI" }, + { 0x1D, "Failure parameters" }, + { 0x1E, "(RF max power reduction)" }, + { 0x1F, "Measured RX_SENS" }, + { 0x20, "Extended cell radius" }, + { 0x21, "reserved" }, + { 0x22, "Success-Failure" }, + { 0x23, "Ack-Nack" }, + { 0x24, "OMU test results" }, + { 0x25, "File identity" }, + { 0x26, "Generation and version code" }, + { 0x27, "SW description" }, + { 0x28, "BCCH LEV" }, + { 0x29, "Test type" }, + { 0x2A, "Subscriber number" }, + { 0x2B, "reserved" }, + { 0x2C, "HSN" }, + { 0x2D, "reserved" }, + { 0x2E, "MS RXLEV" }, + { 0x2F, "MS TXLEV" }, + { 0x30, "RXQUAL" }, + { 0x31, "RX SENS" }, + { 0x32, "Alarm block" }, + { 0x33, "Neighbouring BCCH levels" }, + { 0x34, "STM report type" }, + { 0x35, "MA" }, + { 0x36, "MAIO" }, + { 0x37, "H_FLAG" }, + { 0x38, "TCH_ARFN" }, + { 0x39, "Clock output" }, + { 0x3A, "Transmitted power" }, + { 0x3B, "Clock sync" }, + { 0x3C, "TMS protocol discriminator" }, + { 0x3D, "TMS protocol data" }, + { 0x3E, "FER" }, + { 0x3F, "SWR result" }, + { 0x40, "Object identity" }, + { 0x41, "STM RX Antenna Test" }, + { 0x42, "reserved" }, + { 0x43, "reserved" }, + { 0x44, "Object current state" }, + { 0x45, "reserved" }, + { 0x46, "FU channel configuration" }, + { 0x47, "reserved" }, + { 0x48, "ARFN of a CU" }, + { 0x49, "FU radio definition" }, + { 0x4A, "reserved" }, + { 0x4B, "Severity" }, + { 0x4C, "Diversity selection" }, + { 0x4D, "RX antenna test" }, + { 0x4E, "RX antenna supervision period" }, + { 0x4F, "RX antenna state" }, + { 0x50, "Sector configuration" }, + { 0x51, "Additional info" }, + { 0x52, "SWR parameters" }, + { 0x53, "HW inquiry mode" }, + { 0x54, "reserved" }, + { 0x55, "Availability status" }, + { 0x56, "reserved" }, + { 0x57, "EAC inputs" }, + { 0x58, "EAC outputs" }, + { 0x59, "reserved" }, + { 0x5A, "Position" }, + { 0x5B, "HW unit identity" }, + { 0x5C, "RF test signal attenuation" }, + { 0x5D, "Operational state" }, + { 0x5E, "Logical object identity" }, + { 0x5F, "reserved" }, + { 0x60, "BS_TXPWR_OM" }, + { 0x61, "Loop_Duration" }, + { 0x62, "LNA_Path_Selection" }, + { 0x63, "Serial number" }, + { 0x64, "HW version" }, + { 0x65, "Obj. identity and obj. state" }, + { 0x66, "reserved" }, + { 0x67, "EAC input definition" }, + { 0x68, "EAC id and text" }, + { 0x69, "HW unit status" }, + { 0x6A, "SW release version" }, + { 0x6B, "FW version" }, + { 0x6C, "Bit_Error_Ratio" }, + { 0x6D, "RXLEV_with_Attenuation" }, + { 0x6E, "RXLEV_without_Attenuation" }, + { 0x6F, "reserved" }, + { 0x70, "CU_Results" }, + { 0x71, "reserved" }, + { 0x72, "LNA_Path_Results" }, + { 0x73, "RTE Results" }, + { 0x74, "Real Time" }, + { 0x75, "RX diversity selection" }, + { 0x76, "EAC input config" }, + { 0x77, "Feature support" }, + { 0x78, "File version" }, + { 0x79, "Outputs" }, + { 0x7A, "FU parameters" }, + { 0x7B, "Diagnostic info" }, + { 0x7C, "FU BSIC" }, + { 0x7D, "TRX Configuration" }, + { 0x7E, "Download status" }, + { 0x7F, "RX difference limit" }, + { 0x80, "TRX HW capability" }, + { 0x81, "Common HW config" }, + { 0x82, "Autoconfiguration pool size" }, + { 0x83, "TRE diagnostic info" }, + { 0x84, "TRE object identity" }, + { 0x85, "New TRE Info" }, + { 0x86, "Acknowledgement period" }, + { 0x87, "Synchronization mode" }, + { 0x88, "reserved" }, + { 0x89, "Block Control Data" }, + { 0x8A, "SW load mode" }, + { 0x8B, "Recommended recovery action" }, + { 0x8C, "BSC BCF id" }, + { 0x8D, "Q1 baud rate" }, + { 0x8E, "Allocation status" }, + { 0x8F, "Functional entity number" }, + { 0x90, "Transmission delay" }, + { 0x91, "Loop Duration ms" }, + { 0x92, "Logical channel" }, + { 0x93, "Q1 address" }, + { 0x94, "Alarm detail" }, + { 0x95, "Cabinet type" }, + { 0x96, "HW unit existence" }, + { 0x97, "RF power parameters" }, + { 0x98, "Message scenario" }, + { 0x99, "HW unit max amount" }, + { 0x9A, "Master TRX" }, + { 0x9B, "Transparent data" }, + { 0x9C, "BSC topology info" }, + { 0x9D, "Air i/f modulation" }, + { 0x9E, "LCS Q1 command data" }, + { 0x9F, "Frame number offset" }, + { 0xA0, "Abis TSL" }, + { 0xA1, "Dynamic pool info" }, + { 0xA2, "LCS LLP data" }, + { 0xA3, "LCS Q1 answer data" }, + { 0xA4, "DFCA FU Radio Definition" }, + { 0xA5, "Antenna hopping" }, + { 0xA6, "Field record sequence number" }, + { 0xA7, "Timeslot offslot" }, + { 0xA8, "EPCR capability" }, + { 0xA9, "Connectsite optional element" }, + { 0xAA, "TSC" }, + { 0xAB, "Special TX Power Setting" }, + { 0xAC, "Optional sync settings" }, + { 0xFA, "Abis If parameters" }, + { 0, NULL } +}; + +static const char *get_element_name_string(uint16_t element) { - switch (element) { - case 0x01: - return "Ny1"; - case 0x02: - return "T3105_F"; - case 0x03: - return "Interference band limits"; - case 0x04: - return "Interference report timer in secs"; - case 0x05: - return "Channel configuration per TS"; - case 0x06: - return "BSIC"; - case 0x07: - return "RACH report timer in secs"; - case 0x08: - return "Hardware database status"; - case 0x09: - return "BTS RX level"; - case 0x0A: - return "ARFN"; - case 0x0B: - return "STM antenna attenuation"; - case 0x0C: - return "Cell allocation bitmap"; - case 0x0D: - return "Radio definition per TS"; - case 0x0E: - return "Frame number"; - case 0x0F: - return "Antenna diversity"; - case 0x10: - return "T3105_D"; - case 0x11: - return "File format"; - case 0x12: - return "Last File"; - case 0x13: - return "BTS type"; - case 0x14: - return "Erasure mode"; - case 0x15: - return "Hopping mode"; - case 0x16: - return "Floating TRX"; - case 0x17: - return "Power supplies"; - case 0x18: - return "Reset type"; - case 0x19: - return "Averaging period"; - case 0x1A: - return "RBER2"; - case 0x1B: - return "LAC"; - case 0x1C: - return "CI"; - case 0x1D: - return "Failure parameters"; - case 0x1E: - return "(RF max power reduction)"; - case 0x1F: - return "Measured RX_SENS"; - case 0x20: - return "Extended cell radius"; - case 0x21: - return "reserved"; - case 0x22: - return "Success-Failure"; - case 0x23: - return "Ack-Nack"; - case 0x24: - return "OMU test results"; - case 0x25: - return "File identity"; - case 0x26: - return "Generation and version code"; - case 0x27: - return "SW description"; - case 0x28: - return "BCCH LEV"; - case 0x29: - return "Test type"; - case 0x2A: - return "Subscriber number"; - case 0x2B: - return "reserved"; - case 0x2C: - return "HSN"; - case 0x2D: - return "reserved"; - case 0x2E: - return "MS RXLEV"; - case 0x2F: - return "MS TXLEV"; - case 0x30: - return "RXQUAL"; - case 0x31: - return "RX SENS"; - case 0x32: - return "Alarm block"; - case 0x33: - return "Neighbouring BCCH levels"; - case 0x34: - return "STM report type"; - case 0x35: - return "MA"; - case 0x36: - return "MAIO"; - case 0x37: - return "H_FLAG"; - case 0x38: - return "TCH_ARFN"; - case 0x39: - return "Clock output"; - case 0x3A: - return "Transmitted power"; - case 0x3B: - return "Clock sync"; - case 0x3C: - return "TMS protocol discriminator"; - case 0x3D: - return "TMS protocol data"; - case 0x3E: - return "FER"; - case 0x3F: - return "SWR result"; - case 0x40: - return "Object identity"; - case 0x41: - return "STM RX Antenna Test"; - case 0x42: - return "reserved"; - case 0x43: - return "reserved"; - case 0x44: - return "Object current state"; - case 0x45: - return "reserved"; - case 0x46: - return "FU channel configuration"; - case 0x47: - return "reserved"; - case 0x48: - return "ARFN of a CU"; - case 0x49: - return "FU radio definition"; - case 0x4A: - return "reserved"; - case 0x4B: - return "Severity"; - case 0x4C: - return "Diversity selection"; - case 0x4D: - return "RX antenna test"; - case 0x4E: - return "RX antenna supervision period"; - case 0x4F: - return "RX antenna state"; - case 0x50: - return "Sector configuration"; - case 0x51: - return "Additional info"; - case 0x52: - return "SWR parameters"; - case 0x53: - return "HW inquiry mode"; - case 0x54: - return "reserved"; - case 0x55: - return "Availability status"; - case 0x56: - return "reserved"; - case 0x57: - return "EAC inputs"; - case 0x58: - return "EAC outputs"; - case 0x59: - return "reserved"; - case 0x5A: - return "Position"; - case 0x5B: - return "HW unit identity"; - case 0x5C: - return "RF test signal attenuation"; - case 0x5D: - return "Operational state"; - case 0x5E: - return "Logical object identity"; - case 0x5F: - return "reserved"; - case 0x60: - return "BS_TXPWR_OM"; - case 0x61: - return "Loop_Duration"; - case 0x62: - return "LNA_Path_Selection"; - case 0x63: - return "Serial number"; - case 0x64: - return "HW version"; - case 0x65: - return "Obj. identity and obj. state"; - case 0x66: - return "reserved"; - case 0x67: - return "EAC input definition"; - case 0x68: - return "EAC id and text"; - case 0x69: - return "HW unit status"; - case 0x6A: - return "SW release version"; - case 0x6B: - return "FW version"; - case 0x6C: - return "Bit_Error_Ratio"; - case 0x6D: - return "RXLEV_with_Attenuation"; - case 0x6E: - return "RXLEV_without_Attenuation"; - case 0x6F: - return "reserved"; - case 0x70: - return "CU_Results"; - case 0x71: - return "reserved"; - case 0x72: - return "LNA_Path_Results"; - case 0x73: - return "RTE Results"; - case 0x74: - return "Real Time"; - case 0x75: - return "RX diversity selection"; - case 0x76: - return "EAC input config"; - case 0x77: - return "Feature support"; - case 0x78: - return "File version"; - case 0x79: - return "Outputs"; - case 0x7A: - return "FU parameters"; - case 0x7B: - return "Diagnostic info"; - case 0x7C: - return "FU BSIC"; - case 0x7D: - return "TRX Configuration"; - case 0x7E: - return "Download status"; - case 0x7F: - return "RX difference limit"; - case 0x80: - return "TRX HW capability"; - case 0x81: - return "Common HW config"; - case 0x82: - return "Autoconfiguration pool size"; - case 0x83: - return "TRE diagnostic info"; - case 0x84: - return "TRE object identity"; - case 0x85: - return "New TRE Info"; - case 0x86: - return "Acknowledgement period"; - case 0x87: - return "Synchronization mode"; - case 0x88: - return "reserved"; - case 0x89: - return "Block Control Data"; - case 0x8A: - return "SW load mode"; - case 0x8B: - return "Recommended recovery action"; - case 0x8C: - return "BSC BCF id"; - case 0x8D: - return "Q1 baud rate"; - case 0x8E: - return "Allocation status"; - case 0x8F: - return "Functional entity number"; - case 0x90: - return "Transmission delay"; - case 0x91: - return "Loop Duration ms"; - case 0x92: - return "Logical channel"; - case 0x93: - return "Q1 address"; - case 0x94: - return "Alarm detail"; - case 0x95: - return "Cabinet type"; - case 0x96: - return "HW unit existence"; - case 0x97: - return "RF power parameters"; - case 0x98: - return "Message scenario"; - case 0x99: - return "HW unit max amount"; - case 0x9A: - return "Master TRX"; - case 0x9B: - return "Transparent data"; - case 0x9C: - return "BSC topology info"; - case 0x9D: - return "Air i/f modulation"; - case 0x9E: - return "LCS Q1 command data"; - case 0x9F: - return "Frame number offset"; - case 0xA0: - return "Abis TSL"; - case 0xA1: - return "Dynamic pool info"; - case 0xA2: - return "LCS LLP data"; - case 0xA3: - return "LCS Q1 answer data"; - case 0xA4: - return "DFCA FU Radio Definition"; - case 0xA5: - return "Antenna hopping"; - case 0xA6: - return "Field record sequence number"; - case 0xA7: - return "Timeslot offslot"; - case 0xA8: - return "EPCR capability"; - case 0xA9: - return "Connectsite optional element"; - case 0xAA: - return "TSC"; - case 0xAB: - return "Special TX Power Setting"; - case 0xAC: - return "Optional sync settings"; - case 0xFA: - return "Abis If parameters"; - default: - return "unknown"; - } + return get_value_string(nokia_element_name, element); } static const struct value_string nokia_bts_types[] = { -- cgit v1.2.3 From 1045697c349a432ef4b0a8dfd5ad20549afe2f39 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Fri, 5 Aug 2011 20:11:18 +0200 Subject: Fix MNCC for the NOKIA BTS type (thanks to Gus Bourg) --- openbsc/src/libmsc/gsm_04_08.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index b0bfecadd..bd452ed99 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1705,6 +1705,7 @@ static int tch_recv_mncc(struct gsm_network *net, uint32_t callref, int enable) break; case GSM_BTS_TYPE_BS11: case GSM_BTS_TYPE_RBS2000: + case GSM_BTS_TYPE_NOKIA_SITE: if (enable) return trau_recv_lchan(lchan, callref); return trau_mux_unmap(NULL, callref); @@ -2990,6 +2991,7 @@ int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg) return rtp_send_frame(trans->conn->lchan->abis_ip.rtp_socket, arg); case GSM_BTS_TYPE_BS11: case GSM_BTS_TYPE_RBS2000: + case GSM_BTS_TYPE_NOKIA_SITE: return trau_send_frame(trans->conn->lchan, arg); default: LOGP(DCC, LOGL_ERROR, "Unknown BTS type %u\n", bts->type); -- cgit v1.2.3 From cd98656315c4e81816866823920fc1951f0c2a0b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Aug 2011 23:15:38 +0200 Subject: LAPD: Propagate lapd_receive() errors to the E1 driver Scenario: BTS are configured and working, then the BSC stops working for some reason (crash or administrative stop). If the BSC comes back to life, LAPD among other things does not know about the previous existing TEIs. Instead of ignoring these frames, we notify the driver that we are seeing frames with unknown TEIs, so it can try to recover, e.g. by resending the SABM message. --- openbsc/include/openbsc/signal.h | 1 + openbsc/src/libabis/e1_input.c | 1 + openbsc/src/libabis/input/dahdi.c | 20 ++++++++++++++++---- openbsc/src/libabis/input/lapd.c | 14 ++++++++++++-- openbsc/src/libabis/input/lapd.h | 16 ++++++++++++++-- 5 files changed, 44 insertions(+), 8 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 2991cfac1..71e1deef9 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -145,6 +145,7 @@ enum signal_input { S_INP_NONE, S_INP_TEI_UP, S_INP_TEI_DN, + S_INP_TEI_UNKNOWN, S_INP_LINE_INIT, S_INP_LINE_ALARM, S_INP_LINE_NOALARM, diff --git a/openbsc/src/libabis/e1_input.c b/openbsc/src/libabis/e1_input.c index 97dcd3364..293175e5f 100644 --- a/openbsc/src/libabis/e1_input.c +++ b/openbsc/src/libabis/e1_input.c @@ -570,6 +570,7 @@ int e1inp_event(struct e1inp_ts *ts, int evt, uint8_t tei, uint8_t sapi) if (!link) return -EINVAL; + isd.line = ts->line; isd.link_type = link->type; isd.trx = link->trx; isd.tei = tei; diff --git a/openbsc/src/libabis/input/dahdi.c b/openbsc/src/libabis/input/dahdi.c index a7b45a1af..eb66fa018 100644 --- a/openbsc/src/libabis/input/dahdi.c +++ b/openbsc/src/libabis/input/dahdi.c @@ -100,7 +100,7 @@ static int handle_ts1_read(struct osmo_fd *bfd) struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "DAHDI TS1"); lapd_mph_type prim; unsigned int sapi, tei; - int ilen, ret; + int ilen, ret, error = 0; uint8_t *idata; if (!msg) @@ -122,9 +122,21 @@ static int handle_ts1_read(struct osmo_fd *bfd) DEBUGP(DMI, "<= len = %d, sapi(%d) tei(%d)", ret, sapi, tei); - idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim); - if (!idata && prim == 0) - return -EIO; + idata = lapd_receive(e1i_ts->driver.dahdi.lapd, msg->data, msg->len, &ilen, &prim, &error); + if (!idata) { + switch(error) { + case LAPD_ERR_UNKNOWN_TEI: + /* We don't know about this TEI, probably the BSC + * lost local states (it crashed or it was stopped), + * notify the driver to see if it can do anything to + * recover the existing signalling links with the BTS. + */ + e1inp_event(e1i_ts, S_INP_TEI_UNKNOWN, tei, sapi); + return -EIO; + } + if (prim == 0) + return -EIO; + } msgb_pull(msg, 2); diff --git a/openbsc/src/libabis/input/lapd.c b/openbsc/src/libabis/input/lapd.c index 66ff05e09..2934b58ca 100644 --- a/openbsc/src/libabis/input/lapd.c +++ b/openbsc/src/libabis/input/lapd.c @@ -310,8 +310,9 @@ static void lapd_tei_receive(struct lapd_instance *li, uint8_t *data, int len) }; /* General input function for any data received for this LAPD instance */ -uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, - int *ilen, lapd_mph_type *prim) +uint8_t * +lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len, + int *ilen, lapd_mph_type *prim, int *error) { uint8_t sapi, cr, tei, command; int pf, ns, nr; @@ -327,12 +328,14 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len if (len < 2) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 2, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; }; if ((data[0] & 1) != 0 || (data[1] & 1) != 1) { LOGP(DMI, LOGL_ERROR, "LAPD address field %x/%x not well formed\n", data[0], data[1]); + *error = LAPD_ERR_BAD_ADDR; return NULL; }; @@ -344,6 +347,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len if (len < 3) { LOGP(DMI, LOGL_ERROR, "LAPD receive len %d < 3, ignoring\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; }; @@ -356,6 +360,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_I; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD I frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } ns = data[2] >> 1; @@ -366,6 +371,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len typ = LAPD_TYPE_S; if (len < 4) { LOGP(DMI, LOGL_ERROR, "LAPD S frame, len %d < 4\n", len); + *error = LAPD_ERR_BAD_LEN; return NULL; } nr = data[3] >> 1; @@ -382,6 +388,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len break; default: LOGP(DMI, LOGL_ERROR, "LAPD unknown S cmd %x\n", data[2]); + *error = LAPD_ERR_UNKNOWN_S_CMD; return NULL; }; } else if ((data[2] & 3) == 3) { @@ -414,6 +421,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len default: LOGP(DMI, LOGL_ERROR, "LAPD unknown U cmd %x " "(pf %x data %x)\n", val, pf, data[2]); + *error = LAPD_ERR_UNKNOWN_U_CMD; return NULL; }; }; @@ -429,6 +437,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len teip = teip_from_tei(li, tei); if (!teip) { LOGP(DMI, LOGL_NOTICE, "LAPD Unknown TEI %u\n", tei); + *error = LAPD_ERR_UNKNOWN_TEI; return NULL; } @@ -587,6 +596,7 @@ uint8_t *lapd_receive(struct lapd_instance *li, uint8_t * data, unsigned int len return contents; } + *error = LAPD_ERR_BAD_CMD; return NULL; }; diff --git a/openbsc/src/libabis/input/lapd.h b/openbsc/src/libabis/input/lapd.h index fb980d104..dd22028ab 100644 --- a/openbsc/src/libabis/input/lapd.h +++ b/openbsc/src/libabis/input/lapd.h @@ -26,8 +26,20 @@ struct lapd_instance { struct llist_head tei_list; /* list of TEI in this LAPD instance */ }; -extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data, unsigned int len, - int *ilen, lapd_mph_type *prim); +enum lapd_recv_errors { + LAPD_ERR_NONE = 0, + LAPD_ERR_BAD_LEN, + LAPD_ERR_BAD_ADDR, + LAPD_ERR_UNKNOWN_S_CMD, + LAPD_ERR_UNKNOWN_U_CMD, + LAPD_ERR_UNKNOWN_TEI, + LAPD_ERR_BAD_CMD, + __LAPD_ERR_MAX +}; + +extern uint8_t *lapd_receive(struct lapd_instance *li, uint8_t *data, + unsigned int len, int *ilen, lapd_mph_type *prim, + int *error); extern void lapd_transmit(struct lapd_instance *li, uint8_t tei, uint8_t sapi, uint8_t *data, unsigned int len); -- cgit v1.2.3 From 2962c20f73b0a80f0c31cbaf7bbd600a24aecf94 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 10 Aug 2011 00:48:10 +0200 Subject: NOKIA: Resend SABM on unknown TEI from LAPD --- openbsc/src/libbsc/bts_nokia_site.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bts_nokia_site.c b/openbsc/src/libbsc/bts_nokia_site.c index 6d14bddaf..b5bc2fec0 100644 --- a/openbsc/src/libbsc/bts_nokia_site.c +++ b/openbsc/src/libbsc/bts_nokia_site.c @@ -84,7 +84,7 @@ static int shutdown_om(struct gsm_bts *bts) Attention: this has to be adapted for mISDN */ -static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) +void start_sabm_in_line(struct e1inp_line *line, int start, int sapi) { struct e1inp_sign_link *link; int i; @@ -162,6 +162,13 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, break; } break; + case S_INP_TEI_UNKNOWN: + /* We are receiving LAPD frames with one TEI that we do not + * seem to know, likely that we (the BSC) stopped working + * and lost our local states. However, the BTS is already + * configured, we try to take over the RSL links. */ + start_sabm_in_line(isd->line, 1, SAPI_RSL); + break; } return 0; -- cgit v1.2.3 From f7dc7614c251a31061edfe022d45f05e6c5f4c70 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 10 Aug 2011 02:56:58 +0200 Subject: trau: fix wrong message size for GSM_TCHF_FRAME passed to MNCC During the GSM deployment in the CCC Camp, Daniel Willmann noticed that the LCR and the MNCC were closing the local connection over unix sockets communication quite so often. After some debugging, Peter Stuge noticed that openBSC was closing the connection since write was returning 0. Then, I suggested that it could be a malformed message with zero length. By skipping empty messages, Peter confirmed that the connection between the LCR and the MNCC was not closing anymore. However, there was no voice in the calls that went over MNCC. After some more debugging I found that we were not building GSM_TCHF_FRAME over MNCC appropriately in the TRAU multiplexer code, since we forgot to msgb_put() the message. --- openbsc/src/libtrau/trau_mux.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbsc') diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c index b8b90bd02..5ae5ed74b 100644 --- a/openbsc/src/libtrau/trau_mux.c +++ b/openbsc/src/libtrau/trau_mux.c @@ -212,6 +212,7 @@ int trau_mux_input(struct gsm_e1_subslot *src_e1_ss, } frame->msg_type = GSM_TCHF_FRAME; frame->callref = ue->callref; + msgb_put(msg, sizeof(struct gsm_data_frame) + 33); trau_tx_to_mncc(ue->net, msg); return 0; -- cgit v1.2.3 From 28d9ccbca0cb522c90f551cf4bf243acab7a1944 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Wed, 10 Aug 2011 11:40:54 +0200 Subject: libbsc: Don't free secondary lchan if it is NULL. --- openbsc/src/libbsc/bsc_api.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index 70d641396..ab71ebb3d 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -137,7 +137,11 @@ static void assignment_t10_timeout(void *_conn) LOGP(DMSC, LOGL_ERROR, "Assigment T10 timeout on %p\n", conn); /* normal release on the secondary channel */ - lchan_release(conn->secondary_lchan, 0, 1); + if (conn->secondary_lchan) { + lchan_release(conn->secondary_lchan, 0, 1); + } else { + LOGP(DMSC, LOGL_NOTICE, "Secondary lchan is NULL, not releasing\n"); + } conn->secondary_lchan = NULL; /* inform them about the failure */ -- cgit v1.2.3 From 4da5592c46eafa4bfc4fcf50e88838f4bea6f9ab Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Aug 2011 12:40:07 +0200 Subject: E1 Input: Add VTY command to specify the name of a Line So far, there was no way to set the line->name field at all. --- openbsc/src/libabis/e1_input_vty.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/e1_input_vty.c b/openbsc/src/libabis/e1_input_vty.c index b211e818f..41202b06f 100644 --- a/openbsc/src/libabis/e1_input_vty.c +++ b/openbsc/src/libabis/e1_input_vty.c @@ -41,9 +41,11 @@ #define E1_DRIVER_HELP "mISDN supported E1 Card\n" \ "DAHDI supported E1/T1/J1 Card\n" +#define E1_LINE_HELP "Configure E1/T1/J1 Line\n" "Line Number\n" + DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd, "e1_line <0-255> driver " E1_DRIVER_NAMES, - "Configure E1/T1/J1 Line\n" "Line Number\n" "Set driver for this line\n" + E1_LINE_HELP "Set driver for this line\n" E1_DRIVER_HELP) { struct e1inp_line *line; @@ -63,6 +65,27 @@ DEFUN(cfg_e1line_driver, cfg_e1_line_driver_cmd, return CMD_SUCCESS; } +DEFUN(cfg_e1line_name, cfg_e1_line_name_cmd, + "e1_line <0-255> name .LINE", + E1_LINE_HELP "Set name for this line\n" "Human readable name\n") +{ + struct e1inp_line *line; + int e1_nr = atoi(argv[0]); + + line = e1inp_line_get(e1_nr); + if (!line) { + vty_out(vty, "%% Line %d doesn't exist%s", e1_nr, VTY_NEWLINE); + return CMD_WARNING; + } + if (line->name) { + talloc_free((void *)line->name); + line->name = NULL; + } + line->name = talloc_strdup(line, argv[1]); + + return CMD_SUCCESS; +} + DEFUN(cfg_e1inp, cfg_e1inp_cmd, "e1_input", "Configure E1/T1/J1 TDM input\n") @@ -84,6 +107,9 @@ static int e1inp_config_write(struct vty *vty) llist_for_each_entry(line, &e1inp_line_list, list) { vty_out(vty, " e1_line %u driver %s%s", line->num, line->driver->name, VTY_NEWLINE); + if (line->name) + vty_out(vty, " e1_line %u name %s%s", line->num, + line->name, VTY_NEWLINE); } return CMD_SUCCESS; } @@ -99,6 +125,7 @@ int e1inp_vty_init(void) install_element(CONFIG_NODE, &cfg_e1inp_cmd); install_node(&e1inp_node, e1inp_config_write); install_element(E1INP_NODE, &cfg_e1_line_driver_cmd); + install_element(E1INP_NODE, &cfg_e1_line_name_cmd); return 0; } -- cgit v1.2.3 From 986926ebdec18214b54705c74adddb7aa7a7c7c7 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Aug 2011 12:43:31 +0200 Subject: E1 Input: Move 'show e1_*' command to e1_input_vty.c --- openbsc/src/libabis/e1_input_vty.c | 118 +++++++++++++++++++++++++++++++++++++ openbsc/src/libbsc/bsc_vty.c | 117 ------------------------------------ 2 files changed, 118 insertions(+), 117 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/e1_input_vty.c b/openbsc/src/libabis/e1_input_vty.c index 41202b06f..6055038f3 100644 --- a/openbsc/src/libabis/e1_input_vty.c +++ b/openbsc/src/libabis/e1_input_vty.c @@ -114,6 +114,120 @@ static int e1inp_config_write(struct vty *vty) return CMD_SUCCESS; } +static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv) +{ + vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE); +} + +DEFUN(show_e1drv, + show_e1drv_cmd, + "show e1_driver", + SHOW_STR "Display information about available E1 drivers\n") +{ + struct e1inp_driver *drv; + + llist_for_each_entry(drv, &e1inp_driver_list, list) + e1drv_dump_vty(vty, drv); + + return CMD_SUCCESS; +} + +static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line) +{ + vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s", + line->num, line->name ? line->name : "", + line->driver->name, VTY_NEWLINE); +} + +DEFUN(show_e1line, + show_e1line_cmd, + "show e1_line [line_nr]", + SHOW_STR "Display information about a E1 line\n" + "E1 Line Number\n") +{ + struct e1inp_line *line; + + if (argc >= 1) { + int num = atoi(argv[0]); + llist_for_each_entry(line, &e1inp_line_list, list) { + if (line->num == num) { + e1line_dump_vty(vty, line); + return CMD_SUCCESS; + } + } + return CMD_WARNING; + } + + llist_for_each_entry(line, &e1inp_line_list, list) + e1line_dump_vty(vty, line); + + return CMD_SUCCESS; +} + +static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts) +{ + if (ts->type == E1INP_TS_TYPE_NONE) + return; + vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s", + ts->num, ts->line->num, e1inp_tstype_name(ts->type), + VTY_NEWLINE); +} + +DEFUN(show_e1ts, + show_e1ts_cmd, + "show e1_timeslot [line_nr] [ts_nr]", + SHOW_STR "Display information about a E1 timeslot\n" + "E1 Line Number\n" "E1 Timeslot Number\n") +{ + struct e1inp_line *line = NULL; + struct e1inp_ts *ts; + int ts_nr; + + if (argc == 0) { + llist_for_each_entry(line, &e1inp_line_list, list) { + for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) { + ts = &line->ts[ts_nr]; + e1ts_dump_vty(vty, ts); + } + } + return CMD_SUCCESS; + } + if (argc >= 1) { + int num = atoi(argv[0]); + struct e1inp_line *l; + llist_for_each_entry(l, &e1inp_line_list, list) { + if (l->num == num) { + line = l; + break; + } + } + if (!line) { + vty_out(vty, "E1 line %s is invalid%s", + argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + } + if (argc >= 2) { + ts_nr = atoi(argv[1]); + if (ts_nr >= NUM_E1_TS) { + vty_out(vty, "E1 timeslot %s is invalid%s", + argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + ts = &line->ts[ts_nr]; + e1ts_dump_vty(vty, ts); + return CMD_SUCCESS; + } else { + for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) { + ts = &line->ts[ts_nr]; + e1ts_dump_vty(vty, ts); + } + return CMD_SUCCESS; + } + return CMD_SUCCESS; +} + + struct cmd_node e1inp_node = { E1INP_NODE, "%s(e1_input)#", @@ -127,5 +241,9 @@ int e1inp_vty_init(void) install_element(E1INP_NODE, &cfg_e1_line_driver_cmd); install_element(E1INP_NODE, &cfg_e1_line_name_cmd); + install_element_ve(&show_e1drv_cmd); + install_element_ve(&show_e1line_cmd); + install_element_ve(&show_e1ts_cmd); + return 0; } diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 26ed7d9f4..e9c54faf5 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -975,119 +975,6 @@ DEFUN(show_lchan_summary, return lchan_summary(vty, argc, argv, lchan_dump_short_vty); } -static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv) -{ - vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE); -} - -DEFUN(show_e1drv, - show_e1drv_cmd, - "show e1_driver", - SHOW_STR "Display information about available E1 drivers\n") -{ - struct e1inp_driver *drv; - - llist_for_each_entry(drv, &e1inp_driver_list, list) - e1drv_dump_vty(vty, drv); - - return CMD_SUCCESS; -} - -static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line) -{ - vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s", - line->num, line->name ? line->name : "", - line->driver->name, VTY_NEWLINE); -} - -DEFUN(show_e1line, - show_e1line_cmd, - "show e1_line [line_nr]", - SHOW_STR "Display information about a E1 line\n" - "E1 Line Number\n") -{ - struct e1inp_line *line; - - if (argc >= 1) { - int num = atoi(argv[0]); - llist_for_each_entry(line, &e1inp_line_list, list) { - if (line->num == num) { - e1line_dump_vty(vty, line); - return CMD_SUCCESS; - } - } - return CMD_WARNING; - } - - llist_for_each_entry(line, &e1inp_line_list, list) - e1line_dump_vty(vty, line); - - return CMD_SUCCESS; -} - -static void e1ts_dump_vty(struct vty *vty, struct e1inp_ts *ts) -{ - if (ts->type == E1INP_TS_TYPE_NONE) - return; - vty_out(vty, "E1 Timeslot %2u of Line %u is Type %s%s", - ts->num, ts->line->num, e1inp_tstype_name(ts->type), - VTY_NEWLINE); -} - -DEFUN(show_e1ts, - show_e1ts_cmd, - "show e1_timeslot [line_nr] [ts_nr]", - SHOW_STR "Display information about a E1 timeslot\n" - "E1 Line Number\n" "E1 Timeslot Number\n") -{ - struct e1inp_line *line = NULL; - struct e1inp_ts *ts; - int ts_nr; - - if (argc == 0) { - llist_for_each_entry(line, &e1inp_line_list, list) { - for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) { - ts = &line->ts[ts_nr]; - e1ts_dump_vty(vty, ts); - } - } - return CMD_SUCCESS; - } - if (argc >= 1) { - int num = atoi(argv[0]); - struct e1inp_line *l; - llist_for_each_entry(l, &e1inp_line_list, list) { - if (l->num == num) { - line = l; - break; - } - } - if (!line) { - vty_out(vty, "E1 line %s is invalid%s", - argv[0], VTY_NEWLINE); - return CMD_WARNING; - } - } - if (argc >= 2) { - ts_nr = atoi(argv[1]); - if (ts_nr >= NUM_E1_TS) { - vty_out(vty, "E1 timeslot %s is invalid%s", - argv[1], VTY_NEWLINE); - return CMD_WARNING; - } - ts = &line->ts[ts_nr]; - e1ts_dump_vty(vty, ts); - return CMD_SUCCESS; - } else { - for (ts_nr = 0; ts_nr < NUM_E1_TS; ts_nr++) { - ts = &line->ts[ts_nr]; - e1ts_dump_vty(vty, ts); - } - return CMD_SUCCESS; - } - return CMD_SUCCESS; -} - static void paging_dump_vty(struct vty *vty, struct gsm_paging_request *pag) { vty_out(vty, "Paging on BTS %u%s", pag->bts->nr, VTY_NEWLINE); @@ -2678,10 +2565,6 @@ int bsc_vty_init(const struct log_info *cat) install_element_ve(&show_lchan_summary_cmd); install_element_ve(&logging_fltr_imsi_cmd); - install_element_ve(&show_e1drv_cmd); - install_element_ve(&show_e1line_cmd); - install_element_ve(&show_e1ts_cmd); - install_element_ve(&show_paging_cmd); logging_vty_add_cmds(cat); -- cgit v1.2.3 From 0000ca5885e0e40ce5d12b641992a567f5df1200 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Aug 2011 12:50:13 +0200 Subject: E1 Input: Add rate counters for events related to E1 lines --- openbsc/include/openbsc/e1_input.h | 10 ++++++++++ openbsc/src/libabis/e1_input.c | 35 ++++++++++++++++++++++++++++++++--- openbsc/src/libabis/e1_input_vty.c | 33 ++++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 12 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/e1_input.h b/openbsc/include/openbsc/e1_input.h index 0d79c7d1e..f201c4fb1 100644 --- a/openbsc/include/openbsc/e1_input.h +++ b/openbsc/include/openbsc/e1_input.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #define NUM_E1_TS 32 @@ -19,6 +20,14 @@ enum e1inp_sign_type { }; const char *e1inp_signtype_name(enum e1inp_sign_type tp); +enum e1inp_ctr { + E1I_CTR_HDLC_ABORT, + E1I_CTR_HDLC_BADFCS, + E1I_CTR_HDLC_OVERR, + E1I_CTR_ALARM, + E1I_CTR_REMOVED, +}; + struct e1inp_ts; struct e1inp_sign_link { @@ -107,6 +116,7 @@ struct e1inp_line { struct llist_head list; unsigned int num; const char *name; + struct rate_ctr_group *rate_ctr; /* array of timestlots */ struct e1inp_ts ts[NUM_E1_TS]; diff --git a/openbsc/src/libabis/e1_input.c b/openbsc/src/libabis/e1_input.c index 293175e5f..f73862673 100644 --- a/openbsc/src/libabis/e1_input.c +++ b/openbsc/src/libabis/e1_input.c @@ -39,17 +39,19 @@ #endif #include +#include #include +#include +#include + #include #include #include #include #include -#include #include #include #include -#include #include #include @@ -65,6 +67,31 @@ LLIST_HEAD(e1inp_line_list); static void *tall_sigl_ctx; +static const struct rate_ctr_desc e1inp_ctr_d[] = { + [E1I_CTR_HDLC_ABORT] = { + "hdlc.abort", "ABORT from E1 Layer1" + }, + [E1I_CTR_HDLC_BADFCS] = { + "hdlc.bad_fcs", "Bad Frame Check Sequence" + }, + [E1I_CTR_HDLC_OVERR] = { + "hdlc.overrun", "HDLC Overrun" + }, + [E1I_CTR_ALARM] = { + "alarm", "E1 Alarm (Yellow/Red)" + }, + [E1I_CTR_REMOVED] = { + "removed", "E1 Line removed" + }, +}; + +static const struct rate_ctr_group_desc e1inp_ctr_g_d = { + .group_name_prefix = "e1inp", + .group_description = "E1 Input subsystem", + .num_ctr = ARRAY_SIZE(e1inp_ctr_d), + .ctr_desc = e1inp_ctr_d, +}; + /* * pcap writing of the misdn load * pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat @@ -360,8 +387,10 @@ struct e1inp_line *e1inp_line_create(uint8_t e1_nr, const char *driver_name) return NULL; line->driver = driver; - line->num = e1_nr; + + line->rate_ctr = rate_ctr_group_alloc(line, &e1inp_ctr_g_d, line->num); + for (i = 0; i < NUM_E1_TS; i++) { line->ts[i].num = i+1; line->ts[i].line = line; diff --git a/openbsc/src/libabis/e1_input_vty.c b/openbsc/src/libabis/e1_input_vty.c index 6055038f3..eb34aa188 100644 --- a/openbsc/src/libabis/e1_input_vty.c +++ b/openbsc/src/libabis/e1_input_vty.c @@ -20,23 +20,27 @@ #include #include +#include +#include +#include +#include + #include #include #include #include +#include #include -#include #include #include -#include -#include -#include #include #include #include "../../bscconfig.h" +/* CONFIG */ + #define E1_DRIVER_NAMES "(misdn|dahdi)" #define E1_DRIVER_HELP "mISDN supported E1 Card\n" \ "DAHDI supported E1/T1/J1 Card\n" @@ -114,6 +118,8 @@ static int e1inp_config_write(struct vty *vty) return CMD_SUCCESS; } +/* SHOW */ + static void e1drv_dump_vty(struct vty *vty, struct e1inp_driver *drv) { vty_out(vty, "E1 Input Driver %s%s", drv->name, VTY_NEWLINE); @@ -132,34 +138,43 @@ DEFUN(show_e1drv, return CMD_SUCCESS; } -static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line) +static void e1line_dump_vty(struct vty *vty, struct e1inp_line *line, + int stats) { vty_out(vty, "E1 Line Number %u, Name %s, Driver %s%s", line->num, line->name ? line->name : "", line->driver->name, VTY_NEWLINE); + if (stats) + vty_out_rate_ctr_group(vty, " ", line->rate_ctr); } DEFUN(show_e1line, show_e1line_cmd, - "show e1_line [line_nr]", + "show e1_line [line_nr] [stats]", SHOW_STR "Display information about a E1 line\n" "E1 Line Number\n") { struct e1inp_line *line; + int stats = 0; - if (argc >= 1) { + if (argc >= 1 && strcmp(argv[0], "stats")) { int num = atoi(argv[0]); + if (argc >= 2) + stats = 1; llist_for_each_entry(line, &e1inp_line_list, list) { if (line->num == num) { - e1line_dump_vty(vty, line); + e1line_dump_vty(vty, line, stats); return CMD_SUCCESS; } } return CMD_WARNING; } + if (argc >= 1 && !strcmp(argv[0], "stats")) + stats = 1; + llist_for_each_entry(line, &e1inp_line_list, list) - e1line_dump_vty(vty, line); + e1line_dump_vty(vty, line, stats); return CMD_SUCCESS; } -- cgit v1.2.3 From c21aa18e35c2aa370aa51667d6534502915c4660 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Aug 2011 12:54:07 +0200 Subject: E1 Input: better names for rate counters --- openbsc/src/libabis/e1_input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libabis/e1_input.c b/openbsc/src/libabis/e1_input.c index f73862673..a6661b785 100644 --- a/openbsc/src/libabis/e1_input.c +++ b/openbsc/src/libabis/e1_input.c @@ -69,19 +69,19 @@ static void *tall_sigl_ctx; static const struct rate_ctr_desc e1inp_ctr_d[] = { [E1I_CTR_HDLC_ABORT] = { - "hdlc.abort", "ABORT from E1 Layer1" + "hdlc.abort", "HDLC abort" }, [E1I_CTR_HDLC_BADFCS] = { - "hdlc.bad_fcs", "Bad Frame Check Sequence" + "hdlc.bad_fcs", "HLDC Bad FCS" }, [E1I_CTR_HDLC_OVERR] = { "hdlc.overrun", "HDLC Overrun" }, [E1I_CTR_ALARM] = { - "alarm", "E1 Alarm (Yellow/Red)" + "alarm", "Alarm" }, [E1I_CTR_REMOVED] = { - "removed", "E1 Line removed" + "removed", "Line removed" }, }; -- cgit v1.2.3 From 5da9b52d069af235d2c7c9d04166abda5a26231b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 11 Aug 2011 12:58:52 +0200 Subject: DAHDI: Actually increment e1_input related rate counters --- openbsc/src/libabis/input/dahdi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/libabis/input/dahdi.c b/openbsc/src/libabis/input/dahdi.c index eb66fa018..6802a1e85 100644 --- a/openbsc/src/libabis/input/dahdi.c +++ b/openbsc/src/libabis/input/dahdi.c @@ -40,6 +40,8 @@ #include #include +#include + #include #include #include @@ -68,6 +70,7 @@ static const struct value_string dahdi_evt_names[] = { static void handle_dahdi_exception(struct e1inp_ts *ts) { int rc, evt; + struct e1inp_line *line = ts->line; struct input_signal_data isd; rc = ioctl(ts->driver.dahdi.fd.fd, DAHDI_GETEVENT, &evt); @@ -84,11 +87,24 @@ static void handle_dahdi_exception(struct e1inp_ts *ts) case DAHDI_EVENT_ALARM: /* we should notify the code that the line is gone */ osmo_signal_dispatch(SS_INPUT, S_INP_LINE_ALARM, &isd); + rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_ALARM]); break; case DAHDI_EVENT_NOALARM: /* alarm has gone, we should re-start the SABM requests */ osmo_signal_dispatch(SS_INPUT, S_INP_LINE_NOALARM, &isd); break; + case DAHDI_EVENT_ABORT: + rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_ABORT]); + break; + case DAHDI_EVENT_OVERRUN: + rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_OVERR]); + break; + case DAHDI_EVENT_BADFCS: + rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_HDLC_BADFCS]); + break; + case DAHDI_EVENT_REMOVED: + rate_ctr_inc(&line->rate_ctr->ctr[E1I_CTR_REMOVED]); + break; } } -- cgit v1.2.3 From e8bd9e885dc50f671d2c4af4267b56c84bf7bb6d Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 10 Aug 2011 23:26:33 +0200 Subject: RSL: add timer for lchan activation/deactivation without BTS response The timer callback will simply reset the lchan state to NONE in order to prevent channels getting stuck in 'activation requested' or 'deactivation requested' states. --- openbsc/include/openbsc/gsm_data_shared.h | 1 + openbsc/src/libbsc/abis_rsl.c | 38 ++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h index e3ab5f483..89375cf42 100644 --- a/openbsc/include/openbsc/gsm_data_shared.h +++ b/openbsc/include/openbsc/gsm_data_shared.h @@ -182,6 +182,7 @@ struct gsm_lchan { struct osmo_timer_list T3101; struct osmo_timer_list T3111; struct osmo_timer_list error_timer; + struct osmo_timer_list act_timer; /* table of neighbor cell measurements */ struct neigh_meas_proc neigh_meas[MAX_NEIGH_MEAS]; diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index f20b4f2b5..8a326def9 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -178,6 +178,27 @@ static void print_rsl_cause(int lvl, const uint8_t *cause_v, uint8_t cause_len) LOGPC(DRSL, lvl, "%02x ", cause_v[i]); } +static void lchan_act_tmr_cb(void *data) +{ + struct gsm_lchan *lchan = data; + + LOGP(DRSL, LOGL_NOTICE, "%s Timeout during activation!\n", + gsm_lchan_name(lchan)); + + lchan->state = LCHAN_S_NONE; +} + +static void lchan_deact_tmr_cb(void *data) +{ + struct gsm_lchan *lchan = data; + + LOGP(DRSL, LOGL_NOTICE, "%s Timeout during deactivation!\n", + gsm_lchan_name(lchan)); + + lchan->state = LCHAN_S_NONE; +} + + /* Send a BCCH_INFO message as per Chapter 8.5.1 */ int rsl_bcch_info(struct gsm_bts_trx *trx, uint8_t type, const uint8_t *data, int len) @@ -609,6 +630,11 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) msg->trx->bts->network->T3111 + 2, 0); } + /* Start another timer or assume the BTS sends a ACK/NACK? */ + lchan->act_timer.cb = lchan_deact_tmr_cb; + lchan->act_timer.data = lchan; + osmo_timer_schedule(&lchan->act_timer, 4, 0); + rc = abis_rsl_sendmsg(msg); /* BTS will respond by RF CHAN REL ACK */ @@ -626,6 +652,8 @@ static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan) DEBUGP(DRSL, "%s RF CHANNEL RELEASE ACK\n", gsm_lchan_name(lchan)); + osmo_timer_del(&lchan->act_timer); + if (lchan->state != LCHAN_S_REL_REQ && lchan->state != LCHAN_S_REL_ERR) LOGP(DRSL, LOGL_NOTICE, "%s CHAN REL ACK but state %s\n", gsm_lchan_name(lchan), @@ -791,6 +819,8 @@ static int rsl_rx_chan_act_ack(struct msgb *msg) if (rslh->ie_chan != RSL_IE_CHAN_NR) return -EINVAL; + osmo_timer_del(&msg->lchan->act_timer); + if (msg->lchan->state != LCHAN_S_ACT_REQ) LOGP(DRSL, LOGL_NOTICE, "%s CHAN ACT ACK, but state %s\n", gsm_lchan_name(msg->lchan), @@ -815,6 +845,8 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) struct abis_rsl_dchan_hdr *dh = msgb_l2(msg); struct tlv_parsed tp; + osmo_timer_del(&msg->lchan->act_timer); + LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK", gsm_lchan_name(msg->lchan)); @@ -1257,7 +1289,11 @@ static int rsl_rx_chan_rqd(struct msgb *msg) lchan->rsl_cmode = RSL_CMOD_SPD_SIGN; lchan->tch_mode = GSM48_CMODE_SIGN; - /* FIXME: Start another timer or assume the BTS sends a ACK/NACK? */ + /* Start another timer or assume the BTS sends a ACK/NACK? */ + lchan->act_timer.cb = lchan_act_tmr_cb; + lchan->act_timer.data = lchan; + osmo_timer_schedule(&lchan->act_timer, 4, 0); + rsl_chan_activate_lchan(lchan, 0x00, rqd_ta, 0); DEBUGP(DRSL, "%s Activating ARFCN(%u) SS(%u) lctype %s " -- cgit v1.2.3 From 46f799b224744979294e5f94f225bb1a720e5063 Mon Sep 17 00:00:00 2001 From: Peter Stuge Date: Thu, 11 Aug 2011 04:37:17 +0200 Subject: MNCC: Never send zero-length msgb packets to the socket This will cause the remote end to read 0 bytes, which is interpreted as if we cleanly closed the socket, making the remote end close their side of the socket, which would lead to us closing our side of the socket, so we should never send such a packet. --- openbsc/src/libmsc/mncc_sock.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/libmsc/mncc_sock.c b/openbsc/src/libmsc/mncc_sock.c index 5ef9922d2..d8caf0754 100644 --- a/openbsc/src/libmsc/mncc_sock.c +++ b/openbsc/src/libmsc/mncc_sock.c @@ -165,6 +165,13 @@ static int mncc_sock_write(struct osmo_fd *bfd) bfd->when &= ~BSC_FD_WRITE; + /* bug hunter 8-): maybe someone forgot msgb_put(...) ? */ + if (!msgb_length(msg)) { + LOGP(DMNCC, LOGL_ERROR, "message type (%d) with ZERO " + "bytes!\n", mncc_prim->msg_type); + goto dontsend; + } + /* try to send it over the socket */ rc = write(bfd->fd, msgb_data(msg), msgb_length(msg)); if (rc == 0) @@ -176,6 +183,8 @@ static int mncc_sock_write(struct osmo_fd *bfd) } goto close; } + +dontsend: /* _after_ we send it, we can deueue */ msg2 = msgb_dequeue(&net->upqueue); assert(msg == msg2); -- cgit v1.2.3 From 563d99d3c34861da410bb043d0379b75dfaefdf3 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Thu, 11 Aug 2011 04:40:00 +0200 Subject: libbsc: Only skip lchans with state AND type set to NONE in show lchan The function lchan_alloc only considers lchans to be available if both the type and state are NONE. So change show lchan to list all lchans that are not considered available. --- openbsc/src/libbsc/bsc_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index e9c54faf5..8a5c7fdf2 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -942,7 +942,7 @@ static int lchan_summary(struct vty *vty, int argc, const char **argv, for (lchan_nr = 0; lchan_nr < TS_MAX_LCHAN; lchan_nr++) { lchan = &ts->lchan[lchan_nr]; - if (lchan->type == GSM_LCHAN_NONE) + if ((lchan->type == GSM_LCHAN_NONE) && (lchan->state == LCHAN_S_NONE)) continue; dump_cb(vty, lchan); } -- cgit v1.2.3 From 513da17732fe498c7fddf48b027bd479f356095f Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 11 Aug 2011 04:44:12 +0200 Subject: libbsc: Call lchan_free in the timeout callbacks This makes sure that the lchans can be used again. (state and type are set to NONE) --- openbsc/src/libbsc/abis_rsl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 8a326def9..4b3076322 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -185,7 +185,8 @@ static void lchan_act_tmr_cb(void *data) LOGP(DRSL, LOGL_NOTICE, "%s Timeout during activation!\n", gsm_lchan_name(lchan)); - lchan->state = LCHAN_S_NONE; + rsl_lchan_set_state(lchan, LCHAN_S_NONE); + lchan_free(lchan); } static void lchan_deact_tmr_cb(void *data) @@ -195,7 +196,8 @@ static void lchan_deact_tmr_cb(void *data) LOGP(DRSL, LOGL_NOTICE, "%s Timeout during deactivation!\n", gsm_lchan_name(lchan)); - lchan->state = LCHAN_S_NONE; + rsl_lchan_set_state(lchan, LCHAN_S_NONE); + lchan_free(lchan); } -- cgit v1.2.3 From 7ddc3186878c0665a114b475015ce61c4118ac26 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 11 Aug 2011 04:47:11 +0200 Subject: libbsc: Release the RF channel if BTS thinks it's still in use The Nokia metrosite BTS seem to keep the channels open indefinitely. If osmo-nitb is restarted while one of the channel was still active and tries to activate that channel again the bts would return a CHANNEL ACTIVATE NACK with "Radio channel already activated". This accumulated over the restarts so soon enough no more channels were available. This patch sends a release request to the bts so the channel becomes available again. --- openbsc/src/libbsc/abis_rsl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 4b3076322..c2533667c 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -863,6 +863,9 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) TLVP_LEN(&tp, RSL_IE_CAUSE)); if (*cause != RSL_ERR_RCH_ALR_ACTV_ALLOC) rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE); + else + rsl_rf_chan_release(msg->lchan, 1); + } else rsl_lchan_set_state(msg->lchan, LCHAN_S_NONE); -- cgit v1.2.3 From 6fc6a12c07f9d834c3c9ff01ec948feea0780953 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 11 Aug 2011 04:54:23 +0200 Subject: libbsc: Cosmetic fix for the channel activate NACK log message --- openbsc/src/libbsc/abis_rsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index c2533667c..cb2c9bcc5 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -849,7 +849,7 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) osmo_timer_del(&msg->lchan->act_timer); - LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK", + LOGP(DRSL, LOGL_ERROR, "%s CHANNEL ACTIVATE NACK ", gsm_lchan_name(msg->lchan)); /* BTS has rejected channel activation ?!? */ -- cgit v1.2.3 From fc462dd59ee4772f06c9f2477b36b3f166a8e74b Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Thu, 11 Aug 2011 04:55:45 +0200 Subject: libbsc: Log if a channel is freed with lchan->state != LCHAN_S_NONE I'm not sure if that is an abnormal condition or not, but it seems that lchan state and type have to be none for the lchan to be considered idle. --- openbsc/src/libbsc/chan_alloc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c index c0bdc1be9..6f4fe20f8 100644 --- a/openbsc/src/libbsc/chan_alloc.c +++ b/openbsc/src/libbsc/chan_alloc.c @@ -299,6 +299,10 @@ void lchan_free(struct gsm_lchan *lchan) sig.type = lchan->type; lchan->type = GSM_LCHAN_NONE; + if (lchan->state != LCHAN_S_NONE) { + LOGP(DRLL, LOGL_NOTICE, "Freeing lchan with state %s - setting to NONE\n", gsm_lchans_name(lchan->state)); + lchan->state = LCHAN_S_NONE; + } if (lchan->conn) { struct lchan_signal_data sig; -- cgit v1.2.3 From 013ae46ef67ee560aeaa38e39936a1ae7e35232f Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Sat, 13 Aug 2011 22:45:40 +0200 Subject: bsc: Crash fix for the osmo-nitb/MNCC code It is possible that MNCC sends a MNCC_LCHAN_MODIFY and wants a channel mode that is not possible on the current lchan, in that case a new channel is assigned. We now crash as the osmo-nitb is not having an assignment complete handler, add a NULL check. --- openbsc/src/libbsc/bsc_api.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/libbsc/bsc_api.c b/openbsc/src/libbsc/bsc_api.c index ab71ebb3d..78fee8894 100644 --- a/openbsc/src/libbsc/bsc_api.c +++ b/openbsc/src/libbsc/bsc_api.c @@ -371,7 +371,8 @@ static void handle_ass_compl(struct gsm_subscriber_connection *conn, if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN) rsl_ipacc_crcx(conn->lchan); - api->assign_compl(conn, gh->data[0], + if (api->assign_compl) + api->assign_compl(conn, gh->data[0], lchan_to_chosen_channel(conn->lchan), conn->lchan->encr.alg_id, chan_mode_to_speech(conn->lchan)); -- cgit v1.2.3