From 456a62e98e5e0ac773244191cba092bf58a91988 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 3 May 2020 12:00:52 +0200 Subject: bts_nokia_site: Fix LAPD segfault during reset procedure The existing Nokia *Site code destroyed the LAPD SAP instance for OML while processing an OML message. Once the stack frame returned back to the LAPD code, the LAPD SAP was gone -> segfault. Let's work around this by moving deletion of the LAPD SAP out-of-line by starting a timer 0ms in the future. Not particularly nice, but effective. Change-Id: I6270c7210f600e53f845561898245d2fd30a368d Closes: OS#1761 --- include/osmocom/bsc/gsm_data.h | 2 +- src/osmo-bsc/bts_nokia_site.c | 55 ++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 6996905a4..1d02e3943 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1143,7 +1143,7 @@ struct gsm_bts { no_loc_rel_cnf:1, /* don't wait for RSL REL CONF */ bts_reset_timer_cnf, /* timer for BTS RESET */ did_reset:1, /* we received a RESET ACK */ - wait_reset:1; /* we are waiting for reset to complete */ + wait_reset:2; /* we are waiting for reset to complete */ struct osmo_timer_list reset_timer; } nokia; }; diff --git a/src/osmo-bsc/bts_nokia_site.c b/src/osmo-bsc/bts_nokia_site.c index 66972c2b5..cde0afa97 100644 --- a/src/osmo-bsc/bts_nokia_site.c +++ b/src/osmo-bsc/bts_nokia_site.c @@ -41,6 +41,12 @@ #include +enum reset_timer_state { + RESET_T_NONE = 0, + RESET_T_STOP_LAPD = 1, /* first timer expiration: stop LAPD SAP */ + RESET_T_RESTART_LAPD = 2, /* second timer expiration: restart LAPD SAP */ +}; + /* TODO: put in a separate file ? */ extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg); @@ -1461,18 +1467,28 @@ static void reset_timer_cb(void *_bts) struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; struct e1inp_line *line; - bts->nokia.wait_reset = 0; - /* OML link */ line = e1inp_line_find(e1_link->e1_nr); if (!line) { - LOGP(DLINP, LOGL_ERROR, "BTS %u OML link referring to " - "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr); + LOGP(DLINP, 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 */ + switch (bts->nokia.wait_reset) { + case RESET_T_NONE: /* shouldn't happen */ + break; + case RESET_T_STOP_LAPD: + start_sabm_in_line(line, 0, -1); /* stop all first */ + bts->nokia.wait_reset = RESET_T_RESTART_LAPD; + osmo_timer_schedule(&bts->nokia.reset_timer, bts->nokia.bts_reset_timer_cnf, 0); + break; + case RESET_T_RESTART_LAPD: + bts->nokia.wait_reset = 0; + start_sabm_in_line(line, 0, -1); /* stop all first */ + start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */ + break; + } } /* TODO: put in a separate file ? */ @@ -1574,25 +1590,16 @@ 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. */ - bts->nokia.wait_reset = 1; - - osmo_timer_setup(&bts->nokia.reset_timer, - reset_timer_cb, bts); - osmo_timer_schedule(&bts->nokia.reset_timer, bts->nokia.bts_reset_timer_cnf, 0); - - struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; - struct e1inp_line *line; - /* OML link */ - line = e1inp_line_find(e1_link->e1_nr); - if (!line) { - LOGP(DLINP, 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 */ + /* we cannot delete / stop the OML LAPD SAP right here, as we are in + * the middle of processing an LAPD I frame and are subsequently returning + * back to the LAPD I frame processing code that assumes the SAP is still + * active. So we first schedule the timer at 0ms in the future, where we + * kill all LAPD SAP and re-arm the timer for the reset duration, after which + * we re-create them */ + bts->nokia.wait_reset = RESET_T_STOP_LAPD; + osmo_timer_setup(&bts->nokia.reset_timer, reset_timer_cb, bts); + osmo_timer_schedule(&bts->nokia.reset_timer, 0, 0); } /* ACK for CONF DATA message ? */ -- cgit v1.2.3 From 7d10c80a7dffde379a3e3275e3f29bfd81d91a49 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Wed, 6 May 2020 07:25:25 +0200 Subject: om2k: Properly name message 0x0136, found to be MCTR Statistics Report Signed-off-by: Sylvain Munaut Change-Id: I4b4389fd2e7bf0b3078b8ff60f6ea109114a4475 --- src/osmo-bsc/abis_om2000.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index c32a5fa9a..936fd67ff 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -226,6 +226,10 @@ enum abis_om2k_msgtype { OM2K_MSGT_MCTR_CONFIG_RES_ACK = 0x0130, OM2K_MSGT_MCTR_CONFIG_RES_NACK = 0x0131, OM2K_MSGT_MCTR_CONFIG_RES = 0x0132, + + OM2K_MSGT_MCTR_STATS_REP_ACK = 0x0134, + OM2K_MSGT_MCTR_STATS_REP_NACK = 0x0135, + OM2K_MSGT_MCTR_STATS_REP = 0x0136, }; enum abis_om2k_dei { @@ -558,6 +562,9 @@ static const struct value_string om2k_msgcode_vals[] = { { 0x0130, "MCTR Configuration Result ACK" }, { 0x0131, "MCTR Configuration Result NACK" }, { 0x0132, "MCTR Configuration Result" }, + { 0x0134, "MCTR Statistics report ACK" }, + { 0x0135, "MCTR Statistics report NACK" }, + { 0x0136, "MCTR Statistics report" }, { 0, NULL } }; @@ -2740,8 +2747,8 @@ int abis_om2k_rcvmsg(struct msgb *msg) case OM2K_MSGT_CAPA_RES: rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CAPA_RES_ACK); break; - case 0x0136: /* Unknown ... something for MCTR */ - rc = abis_om2k_tx_simple(bts, &o2h->mo, 0x0134); + case OM2K_MSGT_MCTR_STATS_REP: + rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_MCTR_STATS_REP_ACK); break; /* ERrors */ case OM2K_MSGT_START_REQ_REJ: -- cgit v1.2.3 From 540e98f259b45fd55b119d56e2a9f5e912551833 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 5 May 2020 20:40:02 +0200 Subject: om2k: Use the "from config" TS config to setup OM objects During the configuration of the TS object through OML we must use pchan_from_config since it's too early to use anything else. Signed-off-by: Sylvain Munaut Change-Id: Iecdc911a79b66d8f3d746347710ad697cb288174 --- src/osmo-bsc/abis_om2000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index 936fd67ff..b99fbc584 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -1375,7 +1375,7 @@ static uint8_t ts2comb(struct gsm_bts_trx_ts *ts) * message for it. Rather fail completely right now: */ return 0; } - return pchan2comb(ts->pchan_is); + return pchan2comb(ts->pchan_from_config); } static int put_freq_list(uint8_t *buf, uint16_t arfcn) @@ -1438,7 +1438,7 @@ int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) msgb_tv_put(msg, OM2K_DEI_EXT_RANGE, 0); /* Off */ /* Optional: Interference Rejection Combining */ msgb_tv_put(msg, OM2K_DEI_INTERF_REJ_COMB, 0x00); - switch (ts->pchan_is) { + switch (ts->pchan_from_config) { case GSM_PCHAN_CCCH: msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06); msgb_tv_put(msg, OM2K_DEI_BS_AG_BKS_RES, 0x01); @@ -1482,7 +1482,7 @@ int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) msgb_tv_fixed_put(msg, OM2K_DEI_ICM_BOUND_PARAMS, sizeof(icm_bound_params), icm_bound_params); msgb_tv_put(msg, OM2K_DEI_TTA, 10); /* Timer for Time Alignment */ - if (ts->pchan_is == GSM_PCHAN_TCH_H) + if (ts->pchan_from_config == GSM_PCHAN_TCH_H) msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 1); /* TCH/H */ else msgb_tv_put(msg, OM2K_DEI_ICM_CHAN_RATE, 0); /* TCH/F */ -- cgit v1.2.3 From 586c0114b38e73ca5a862067f00410bb0e2a8cc8 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Wed, 6 May 2020 11:49:08 +0200 Subject: om2k: Dispatch TS_EV_OML_READY to TS FSM only when it's actually ready Signed-off-by: Sylvain Munaut Change-Id: Ic2a84ea406e9a39332313d63b27d73f334d4e0a0 --- src/osmo-bsc/abis_om2000.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index b99fbc584..9ae5a2644 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -2019,7 +2019,7 @@ enum om2k_trx_state { struct om2k_trx_fsm_priv { struct gsm_bts_trx *trx; - uint8_t next_ts_nr; + uint8_t cur_ts_nr; }; static void om2k_trx_s_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -2063,8 +2063,8 @@ static void om2k_trx_s_wait_rx(struct osmo_fsm_inst *fi, uint32_t event, void *d /* Initialize Timeslots after TX */ osmo_fsm_inst_state_chg(fi, OM2K_TRX_S_WAIT_TS, TRX_FSM_TIMEOUT, 0); - otfp->next_ts_nr = 0; - ts = &otfp->trx->ts[otfp->next_ts_nr++]; + otfp->cur_ts_nr = 0; + ts = &otfp->trx->ts[otfp->cur_ts_nr]; om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx, &ts->rbs2000.om2k_mo); } @@ -2074,9 +2074,14 @@ static void om2k_trx_s_wait_ts(struct osmo_fsm_inst *fi, uint32_t event, void *d struct om2k_trx_fsm_priv *otfp = fi->priv; struct gsm_bts_trx_ts *ts; - if (otfp->next_ts_nr < 8) { + /* notify TS is ready */ + ts = &otfp->trx->ts[otfp->cur_ts_nr]; + osmo_fsm_inst_dispatch(ts->fi, TS_EV_OML_READY, NULL); + + /* next ? */ + if (++otfp->cur_ts_nr < 8) { /* iterate to the next timeslot */ - ts = &otfp->trx->ts[otfp->next_ts_nr++]; + ts = &otfp->trx->ts[otfp->cur_ts_nr]; om2k_mo_fsm_start(fi, OM2K_TRX_EVT_TS_DONE, otfp->trx, &ts->rbs2000.om2k_mo); } else { @@ -2820,7 +2825,6 @@ void abis_om2k_trx_init(struct gsm_bts_trx *trx) om2k_mo_init(&ts->rbs2000.om2k_mo, OM2K_MO_CLS_TS, bts->nr, trx->nr, i); OSMO_ASSERT(ts->fi); - osmo_fsm_inst_dispatch(ts->fi, TS_EV_OML_READY, NULL); } } -- cgit v1.2.3 From 4a048d363b7e6c63816b9ae4d30cadabefed0a1a Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 5 May 2020 21:06:33 +0200 Subject: om2k: Fix the frequency specifier for TX/RX/TS conf requests * OM2K_DEI_FREQ_SPEC_RX: (hop << 15) | (rx_addr << 10) | arfcn . hop Hopping marker . rx_addr is not really the TRX number, it's just a sequential number different for all TRX, doesn't need to be 'in-order' of TRX . arfcn The ARFCN number (0 for hopping and 1023 for 'no frequency') * OM2K_DEI_FREQ_SPEC_TX: (hop << 15) | (tx_id << 10) | arfcn tx_id Pretty much same as rx_id except here we know that the order doesn't have to match TRX order. It seems to even vary from one reboot to another on some real-world capture we got. . hop Hopping marker . tx_addr Same as 'rx_addr' above but for TX . arfcn The ARFCN number (0 for hopping and 1023 for 'no frequency') * OM2K_DEI_FREQ_LIST: Groups of 3 bytes (24 bits), 1 per frequency used. (tx_addr << 20) | (rx_addr << 16) | (is_c0 << 10) | arfcn . tx_addr See above . rx_addr See above . is_c0 Must be 1 if that ARFCN hosts the C0. (first TRX of a MCTR) . arfcn The ARFCN number (Note MAIO must also be set properly on the different TRX/TS sharing a frequency ... ) The way we generate theses here is what we gathered from real-world traces: - Each 'TX' of each TRX is set to the ARFCN set in that TRX config - Each 'RX' of each TRX is configures as 'hopping' (which I assume means it will just pick the appropriate freq ?) - For each TS, we use : . tx_addr of the TRX that has the ARFCN we want to TX on . rx_addr of the TRX where the TS we're configuring is . arfcn The actual ARFCN we want to add to the list This is incomplete but will work for the 1 MCTR case. Config for multiple MCTR or multiple virtual-bts still need to be handled but it's not yet known exactly how those need to be configured. Signed-off-by: Sylvain Munaut Change-Id: Ie39a857543adaa11d1822346d8563ce3718412c8 --- src/osmo-bsc/abis_om2000.c | 45 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index 9ae5a2644..e20d9a65e 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -1285,7 +1285,8 @@ int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx) o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); fill_om2k_hdr(o2k, &mo, OM2K_MSGT_RX_CONF_REQ); - msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_RX, trx->arfcn); + /* OM2K_DEI_FREQ_SPEC_RX: Using trx_nr as "RX address" only works for single MCTR case */ + msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_RX, 0x8000 | ((uint16_t)trx->nr << 10)); msgb_tv_put(msg, OM2K_DEI_RX_DIVERSITY, 0x02); /* A */ return abis_om2k_sendmsg(trx->bts, msg); @@ -1303,9 +1304,10 @@ int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx) o2k = (struct abis_om2k_hdr *) msgb_put(msg, sizeof(*o2k)); fill_om2k_hdr(o2k, &mo, OM2K_MSGT_TX_CONF_REQ); - msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_TX, trx->arfcn); + /* OM2K_DEI_FREQ_SPEC_TX: Using trx_nr as "TX address" only works for single MCTR case */ + msgb_tv16_put(msg, OM2K_DEI_FREQ_SPEC_TX, trx->arfcn | ((uint16_t)trx->nr << 10)); msgb_tv_put(msg, OM2K_DEI_POWER, trx->nominal_power-trx->max_power_red); - msgb_tv_put(msg, OM2K_DEI_FILLING_MARKER, 0); /* Filling enabled */ + msgb_tv_put(msg, OM2K_DEI_FILLING_MARKER, trx != trx->bts->c0); /* Filling enabled for C0 only */ msgb_tv_put(msg, OM2K_DEI_BCC, trx->bts->bsic & 0x7); /* Dedication Information is optional */ @@ -1378,12 +1380,41 @@ static uint8_t ts2comb(struct gsm_bts_trx_ts *ts) return pchan2comb(ts->pchan_from_config); } -static int put_freq_list(uint8_t *buf, uint16_t arfcn) +static int put_freq_list(uint8_t *buf, struct gsm_bts_trx_ts *ts, uint16_t arfcn) { - buf[0] = 0x00; /* TX/RX address */ + struct gsm_bts_trx *trx; + + /* Find the TRX that's configured for that ARFCN */ + llist_for_each_entry(trx, &ts->trx->bts->trx_list, list) + if (trx->arfcn == arfcn) + break; + + if (!trx || (trx->arfcn != arfcn)) { + LOGP(DNM, LOGL_ERROR, "Trying to use ARFCN %d for hopping with no TRX configured for it", arfcn); + return 0; + } + + /* + * [7:4] - TX address + * This must be the same number that was used when configuring the TX + * MO object with that target arfcn + * + * [3:0] - RX address + * The logical TRX number we're configuring the hopping sequence for + * This must basically match the MO object instance number + * + * ATM since we only support 1 MCTR, we use trx->nr + */ + buf[0] = (trx->nr << 4) | ts->trx->nr; + + /* ARFCN Number */ buf[1] = (arfcn >> 8); buf[2] = (arfcn & 0xff); + /* C0 marker */ + if (trx == trx->bts->c0) + buf[1] |= 0x04; + return 3; } @@ -1397,10 +1428,10 @@ static int om2k_gen_freq_list(uint8_t *list, struct gsm_bts_trx_ts *ts) unsigned int i; for (i = 0; i < ts->hopping.arfcns.data_len*8; i++) { if (bitvec_get_bit_pos(&ts->hopping.arfcns, i)) - cur += put_freq_list(cur, i); + cur += put_freq_list(cur, ts, i); } } else - cur += put_freq_list(cur, ts->trx->arfcn); + cur += put_freq_list(cur, ts, ts->trx->arfcn); len = cur - list; -- cgit v1.2.3 From d1f1884dfdc6a19490b6f5f8a61b3d0fba247b1f Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Wed, 6 May 2020 14:10:46 +0200 Subject: bts_ericsson_rbs2000: Init all the TRX, not just C0 Signed-off-by: Sylvain Munaut Change-Id: I9417f433f759ce21b8b6e0b74cd686df5388f8c5 --- src/osmo-bsc/bts_ericsson_rbs2000.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/osmo-bsc/bts_ericsson_rbs2000.c b/src/osmo-bsc/bts_ericsson_rbs2000.c index 4d1e91b0f..f98c647b0 100644 --- a/src/osmo-bsc/bts_ericsson_rbs2000.c +++ b/src/osmo-bsc/bts_ericsson_rbs2000.c @@ -34,11 +34,15 @@ static void bootstrap_om_bts(struct gsm_bts *bts) { + struct gsm_bts_trx *trx; + LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr); - /* FIXME: this is global init, not bootstrapping */ + /* Global init (not bootstrapping) */ abis_om2k_bts_init(bts); - abis_om2k_trx_init(bts->c0); + + llist_for_each_entry(trx, &bts->trx_list, list) + abis_om2k_trx_init(trx); /* TODO: Should we wait for a Failure report? */ om2k_bts_fsm_start(bts); -- cgit v1.2.3 From ce0b5627856a4d6e7b2e3731d5cc1fe1f0cd269a Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Thu, 7 May 2020 14:30:51 +0200 Subject: bts_ericsson_rbs2000: Whitelist the E1d input driver Signed-off-by: Sylvain Munaut Change-Id: Ief9093706d6ca20f8162ca541dcc4669c13e2cbc --- src/osmo-bsc/bts_ericsson_rbs2000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/osmo-bsc/bts_ericsson_rbs2000.c b/src/osmo-bsc/bts_ericsson_rbs2000.c index f98c647b0..02ef46387 100644 --- a/src/osmo-bsc/bts_ericsson_rbs2000.c +++ b/src/osmo-bsc/bts_ericsson_rbs2000.c @@ -153,14 +153,16 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, case S_L_INP_LINE_NOALARM: if (strcasecmp(isd->line->driver->name, "DAHDI") && strcasecmp(isd->line->driver->name, "MISDN_LAPD") - && strcasecmp(isd->line->driver->name, "UNIXSOCKET")) + && strcasecmp(isd->line->driver->name, "UNIXSOCKET") + && strcasecmp(isd->line->driver->name, "E1D")) break; start_sabm_in_line(isd->line, 1); break; case S_L_INP_LINE_ALARM: if (strcasecmp(isd->line->driver->name, "DAHDI") && strcasecmp(isd->line->driver->name, "MISDN_LAPD") - && strcasecmp(isd->line->driver->name, "UNIXSOCKET")) + && strcasecmp(isd->line->driver->name, "UNIXSOCKET") + && strcasecmp(isd->line->driver->name, "E1D")) break; start_sabm_in_line(isd->line, 0); break; -- cgit v1.2.3 From dbd1b50604a36b6a5adb01d36796e19c1320a0c3 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 5 May 2020 21:07:58 +0200 Subject: om2k: Add option to limit OML version during negotiation Starting from G12R13 the MCTR swiches to BSC controlled mode. And although we think we know how to configure it (via MCTR Conf Req), something doesn't work right and the timeslot configuration is not accepted. (TS Conf Result shows "Data not according to request"). So as a workaround for now, we use this version of the protocol where we don't configure the MCTR (it's in "BTS controlled mode") and with this protocol, the BTS accepts our timeslot config and we can bring the system up. This commit add a generic option to limit either OML or RSL IWD version to any value. It also keeps track of the actual negotation version so we can react to it in other places of the code. Signed-off-by: Sylvain Munaut Change-Id: I8f0b0ba72056ea4250fe490e7a38630c77c04f65 better version limit Change-Id: Ia789f8ede3eab7eeca6c759da0109e0b53398f60 --- include/osmocom/bsc/gsm_data.h | 4 ++++ src/osmo-bsc/abis_om2000.c | 52 +++++++++++++++++++++++++++++++++++------- src/osmo-bsc/abis_om2000_vty.c | 43 ++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 1d02e3943..c2115a628 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1135,6 +1135,10 @@ struct gsm_bts { struct gsm_abis_mo mo; } tf; uint32_t use_superchannel:1; + struct { + uint16_t limit; + uint16_t active; + } om2k_version[16]; } rbs2000; struct { uint8_t bts_type; diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index e20d9a65e..f5d8095fc 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -2447,8 +2447,8 @@ static int abis_om2k_tx_negot_req_ack(struct gsm_bts *bts, const struct abis_om2 } struct iwd_version { - uint8_t gen_char[3+1]; - uint8_t rev_char[3+1]; + char gen_char[3+1]; + char rev_char[3+1]; }; struct iwd_type { @@ -2459,11 +2459,13 @@ struct iwd_type { static int om2k_rx_negot_req(struct msgb *msg) { struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)msg->dst; + struct gsm_bts *bts = sign_link->trx->bts; struct abis_om2k_hdr *o2h = msgb_l2(msg); struct iwd_type iwd_types[16]; uint8_t num_iwd_types = o2h->data[2]; uint8_t *cur = o2h->data+3; - unsigned int i, v; + unsigned int i; + int v; uint8_t out_buf[1024]; uint8_t *out_cur = out_buf+1; @@ -2494,25 +2496,59 @@ static int om2k_rx_negot_req(struct msgb *msg) /* Select the last version for each IWD type */ for (i = 0; i < ARRAY_SIZE(iwd_types); i++) { struct iwd_type *type = &iwd_types[i]; - struct iwd_version *last_v; + struct iwd_version *sel_v = NULL, *alt_v = NULL; + uint16_t sel_ver, alt_ver = 0; + int gen, rev; if (type->num_vers == 0) continue; out_num_types++; - last_v = &type->v[type->num_vers-1]; + for (v = type->num_vers-1; v >= 0; v--) { + if ((sscanf(type->v[v].gen_char, "G%2d", &gen) != 1) || + (sscanf(type->v[v].rev_char, "R%2d", &rev) != 1)) + continue; + sel_ver = (gen << 8) | rev; + + if (!alt_v) { + alt_ver = sel_ver; + alt_v = &type->v[v]; + } + + if ((bts->rbs2000.om2k_version[i].limit != 0) && + (bts->rbs2000.om2k_version[i].limit < sel_ver)) + continue; + + sel_v = &type->v[v]; + break; + } + if (!sel_v) { + if (!alt_v) { + LOGP(DNM, LOGL_ERROR, "Couldn't find valid version for IWD Type %u." + "Skipping IWD ... this will most likely fail\n", i); + continue; + } else { + sel_v = alt_v; + sel_ver = alt_ver; + LOGP(DNM, LOGL_ERROR, "Couldn't find suitable version for IWD Type %u." + "Fallback to Gen %s Rev %s\n", i, + sel_v->gen_char, sel_v->rev_char); + } + } + + bts->rbs2000.om2k_version[i].active = sel_ver; *out_cur++ = i; - memcpy(out_cur, last_v->gen_char, 3); + memcpy(out_cur, sel_v->gen_char, 3); out_cur += 3; - memcpy(out_cur, last_v->rev_char, 3); + memcpy(out_cur, sel_v->rev_char, 3); out_cur += 3; } out_buf[0] = out_num_types; - return abis_om2k_tx_negot_req_ack(sign_link->trx->bts, &o2h->mo, out_buf, out_cur - out_buf); + return abis_om2k_tx_negot_req_ack(bts, &o2h->mo, out_buf, out_cur - out_buf); } diff --git a/src/osmo-bsc/abis_om2000_vty.c b/src/osmo-bsc/abis_om2000_vty.c index 972fff04a..222546f87 100644 --- a/src/osmo-bsc/abis_om2000_vty.c +++ b/src/osmo-bsc/abis_om2000_vty.c @@ -467,6 +467,40 @@ DEFUN(cfg_bts_alt_mode, cfg_bts_alt_mode_cmd, return CMD_SUCCESS; } +DEFUN(cfg_bts_om2k_version_limit, cfg_bts_om2k_version_limit_cmd, + "om2000 version-limit (oml|rsl) gen <0-99> rev <0-99>", + "Configure OM2K specific parameters\n" + "Configure optional maximum protocol version to negotiate\n" + "Limit OML IWD version\n" "Limit RSL IWD version\n" + "Generation limit\n" + "Generation number to limit to (inclusive)\n" + "Revision limit\n" + "Revision number to limit to (inclusive)\n") +{ + struct gsm_bts *bts = vty->index; + int iwd; + + if (bts->type != GSM_BTS_TYPE_RBS2000) { + vty_out(vty, "%% Command only works for RBS2000%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if (!strcmp(argv[0], "oml")) + iwd = 0; + else if (!strcmp(argv[0], "rsl")) + iwd = 1; + else { + vty_out(vty, "%% Invalid IWD%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + bts->rbs2000.om2k_version[iwd].limit = (atoi(argv[1]) << 8) | atoi(argv[2]); + + return CMD_SUCCESS; +} + DEFUN(cfg_bts_is_conn_list, cfg_bts_is_conn_list_cmd, "is-connection-list (add|del) <0-2047> <0-2047> <0-255>", "Interface Switch Connection List\n" @@ -591,6 +625,7 @@ void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts) { struct is_conn_group *igrp; struct con_group *cgrp; + unsigned int i; llist_for_each_entry(igrp, &bts->rbs2000.is.conn_groups, list) vty_out(vty, " is-connection-list add %u %u %u%s", @@ -604,6 +639,13 @@ void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts) if (bts->rbs2000.use_superchannel) vty_out(vty, " abis-lower-transport super-channel%s", VTY_NEWLINE); + for (i = 0; i < 2; i++) + if (bts->rbs2000.om2k_version[i].limit) + vty_out(vty, " om2000 version-limit %s gen %02d rev %02d%s", + i ? "rsl" : "oml", + (bts->rbs2000.om2k_version[i].limit >> 8), + (bts->rbs2000.om2k_version[i].limit & 0xff), + VTY_NEWLINE); } int abis_om2k_vty_init(void) @@ -631,6 +673,7 @@ int abis_om2k_vty_init(void) install_element(BTS_NODE, &cfg_bts_is_conn_list_cmd); install_element(BTS_NODE, &cfg_bts_alt_mode_cmd); + install_element(BTS_NODE, &cfg_bts_om2k_version_limit_cmd); install_element(BTS_NODE, &cfg_om2k_con_group_cmd); install_element(BTS_NODE, &del_om2k_con_group_cmd); -- cgit v1.2.3 From a40b75e44d5ba53facd81f54d9648cb1175eae36 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 5 May 2020 20:09:36 +0200 Subject: om2k: Rename MCTR config request constants for consistency Signed-off-by: Sylvain Munaut Change-Id: I776b0016837e018500ef69acb2f30a274008818e --- src/osmo-bsc/abis_om2000.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index f5d8095fc..dc233c69a 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -219,13 +219,13 @@ enum abis_om2k_msgtype { OM2K_MSGT_FEATURE_CTRL_COMPL = 0x011a, OM2K_MSGT_FEATURE_CTRL_REJ = 0x011b, - OM2K_MSGT_MCTR_CONFIG_REQ = 0x012c, - OM2K_MSGT_MCTR_CONFIG_REQ_ACK = 0x012e, - OM2K_MSGT_MCTR_CONFIG_REQ_REJ = 0x012f, + OM2K_MSGT_MCTR_CONF_REQ = 0x012c, + OM2K_MSGT_MCTR_CONF_REQ_ACK = 0x012e, + OM2K_MSGT_MCTR_CONF_REQ_REJ = 0x012f, - OM2K_MSGT_MCTR_CONFIG_RES_ACK = 0x0130, - OM2K_MSGT_MCTR_CONFIG_RES_NACK = 0x0131, - OM2K_MSGT_MCTR_CONFIG_RES = 0x0132, + OM2K_MSGT_MCTR_CONF_RES_ACK = 0x0130, + OM2K_MSGT_MCTR_CONF_RES_NACK = 0x0131, + OM2K_MSGT_MCTR_CONF_RES = 0x0132, OM2K_MSGT_MCTR_STATS_REP_ACK = 0x0134, OM2K_MSGT_MCTR_STATS_REP_NACK = 0x0135, -- cgit v1.2.3 From cbaa1799457c9a97f361e0765447436732294450 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Tue, 5 May 2020 20:14:44 +0200 Subject: om2k: Add support for MCTR configuration Currently only supports a single MCTR with fixed configuration Signed-off-by: Sylvain Munaut Change-Id: I96b8bb2c01c05bf153fc924f62bd6aafa96725ee --- include/osmocom/bsc/gsm_data.h | 4 +++ src/osmo-bsc/abis_om2000.c | 80 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index c2115a628..3fd466c3a 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1134,6 +1134,10 @@ struct gsm_bts { struct om2k_mo om2k_mo; struct gsm_abis_mo mo; } tf; + struct { + struct om2k_mo om2k_mo; + struct gsm_abis_mo mo; + } mctr; uint32_t use_superchannel:1; struct { uint16_t limit; diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index dc233c69a..2380f5c8d 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -30,6 +30,7 @@ #include +#include #include #include #include @@ -778,6 +779,9 @@ get_om2k_mo(struct gsm_bts *bts, const struct abis_om2k_mo *abis_mo) case OM2K_MO_CLS_TF: mo = &bts->rbs2000.tf.om2k_mo; break; + case OM2K_MO_CLS_MCTR: + mo = &bts->rbs2000.mctr.om2k_mo; + break; case OM2K_MO_CLS_TRXC: trx = gsm_bts_trx_num(bts, abis_mo->inst); @@ -1254,6 +1258,35 @@ int abis_om2k_tx_con_conf_req(struct gsm_bts *bts) return abis_om2k_sendmsg(bts, msg); } +int abis_om2k_tx_mctr_conf_req(struct gsm_bts *bts) +{ + struct msgb *msg = om2k_msgb_alloc(); + struct abis_om2k_hdr *o2k; + struct gsm_bts_trx *trx; + uint8_t trxc_list = 0; + const uint8_t features[] = { 0x00 }; + + /* build trxc list */ + llist_for_each_entry(trx, &bts->trx_list, list) + trxc_list |= (1 << trx->nr); + + /* fill message */ + msgb_tv16_put(msg, OM2K_DEI_TRXC_LIST, osmo_swab16(trxc_list)); /* Read as LE by the BTS ... */ + msgb_tv_put (msg, OM2K_DEI_MAX_ALLOWED_POWER, 0x31); + msgb_tv_put (msg, OM2K_DEI_MAX_ALLOWED_NUM_TRXCS, 0x08); + msgb_tlv_put (msg, OM2K_DEI_MCTR_FEAT_STATUS_BMAP, 1, features); + + /* pre-pend the OM2K header */ + o2k = (struct abis_om2k_hdr *) msgb_push(msg, sizeof(*o2k)); + fill_om2k_hdr(o2k, &bts->rbs2000.mctr.om2k_mo.addr, + OM2K_MSGT_MCTR_CONF_REQ); + DEBUGP(DNM, "Tx MO=%s %s\n", + om2k_mo_name(&bts->rbs2000.mctr.om2k_mo.addr), + get_value_string(om2k_msgcode_vals, OM2K_MSGT_MCTR_CONF_REQ)); + + return abis_om2k_sendmsg(bts, msg); +} + static void om2k_trx_to_mo(struct abis_om2k_mo *mo, const struct gsm_bts_trx *trx, enum abis_om2k_mo_cls cls) @@ -1708,6 +1741,9 @@ static void om2k_mo_st_wait_start_res(struct osmo_fsm_inst *fi, uint32_t event, case OM2K_MO_CLS_CON: abis_om2k_tx_con_conf_req(omfp->trx->bts); break; + case OM2K_MO_CLS_MCTR: + abis_om2k_tx_mctr_conf_req(omfp->trx->bts); + break; case OM2K_MO_CLS_TX: abis_om2k_tx_tx_conf_req(omfp->trx); break; @@ -1975,6 +2011,7 @@ int om2k_mo_fsm_recvmsg(struct gsm_bts *bts, struct om2k_mo *mo, case OM2K_MSGT_CON_CONF_REQ_ACK: case OM2K_MSGT_IS_CONF_REQ_ACK: + case OM2K_MSGT_MCTR_CONF_REQ_ACK: case OM2K_MSGT_RX_CONF_REQ_ACK: case OM2K_MSGT_TF_CONF_REQ_ACK: case OM2K_MSGT_TS_CONF_REQ_ACK: @@ -1985,6 +2022,7 @@ int om2k_mo_fsm_recvmsg(struct gsm_bts *bts, struct om2k_mo *mo, case OM2K_MSGT_CON_CONF_RES: case OM2K_MSGT_IS_CONF_RES: + case OM2K_MSGT_MCTR_CONF_RES: case OM2K_MSGT_RX_CONF_RES: case OM2K_MSGT_TF_CONF_RES: case OM2K_MSGT_TS_CONF_RES: @@ -2222,6 +2260,7 @@ enum om2k_bts_event { OM2K_BTS_EVT_IS_DONE, OM2K_BTS_EVT_CON_DONE, OM2K_BTS_EVT_TF_DONE, + OM2K_BTS_EVT_MCTR_DONE, OM2K_BTS_EVT_TRX_DONE, OM2K_BTS_EVT_STOP, }; @@ -2232,6 +2271,7 @@ static const struct value_string om2k_bts_events[] = { { OM2K_BTS_EVT_IS_DONE, "IS-DONE" }, { OM2K_BTS_EVT_CON_DONE, "CON-DONE" }, { OM2K_BTS_EVT_TF_DONE, "TF-DONE" }, + { OM2K_BTS_EVT_MCTR_DONE, "MCTR-DONE" }, { OM2K_BTS_EVT_TRX_DONE, "TRX-DONE" }, { OM2K_BTS_EVT_STOP, "STOP" }, { 0, NULL } @@ -2243,6 +2283,7 @@ enum om2k_bts_state { OM2K_BTS_S_WAIT_IS, OM2K_BTS_S_WAIT_CON, OM2K_BTS_S_WAIT_TF, + OM2K_BTS_S_WAIT_MCTR, OM2K_BTS_S_WAIT_TRX, OM2K_BTS_S_DONE, OM2K_BTS_S_ERROR, @@ -2306,10 +2347,33 @@ static void om2k_bts_s_wait_con(struct osmo_fsm_inst *fi, uint32_t event, void * static void om2k_bts_s_wait_is(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct om2k_bts_fsm_priv *obfp = fi->priv; - struct gsm_bts_trx *trx; + struct gsm_bts *bts = obfp->bts; OSMO_ASSERT(event == OM2K_BTS_EVT_IS_DONE); + /* If we're running OML >= G12R13, start MCTR, else skip directly to TRX */ + if (bts->rbs2000.om2k_version[0].active >= 0x0c0d) { + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_MCTR, + BTS_FSM_TIMEOUT, 0); + om2k_mo_fsm_start(fi, OM2K_BTS_EVT_MCTR_DONE, bts->c0, + &bts->rbs2000.mctr.om2k_mo); + } else { + struct gsm_bts_trx *trx; + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX, + BTS_FSM_TIMEOUT, 0); + obfp->next_trx_nr = 0; + trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++); + om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE); + } +} + +static void om2k_bts_s_wait_mctr(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct om2k_bts_fsm_priv *obfp = fi->priv; + struct gsm_bts_trx *trx; + + OSMO_ASSERT(event == OM2K_BTS_EVT_MCTR_DONE); + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX, BTS_FSM_TIMEOUT, 0); obfp->next_trx_nr = 0; @@ -2368,10 +2432,18 @@ static const struct osmo_fsm_state om2k_bts_states[] = { [OM2K_BTS_S_WAIT_IS] = { .in_event_mask = S(OM2K_BTS_EVT_IS_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | + S(OM2K_BTS_S_WAIT_MCTR) | S(OM2K_BTS_S_WAIT_TRX), .name = "WAIT-IS", .action = om2k_bts_s_wait_is, }, + [OM2K_BTS_S_WAIT_MCTR] = { + .in_event_mask = S(OM2K_BTS_EVT_MCTR_DONE), + .out_state_mask = S(OM2K_BTS_S_ERROR) | + S(OM2K_BTS_S_WAIT_TRX), + .name = "WAIT-MCTR", + .action = om2k_bts_s_wait_mctr, + }, [OM2K_BTS_S_WAIT_TRX] = { .in_event_mask = S(OM2K_BTS_EVT_TRX_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | @@ -2792,6 +2864,9 @@ int abis_om2k_rcvmsg(struct msgb *msg) case OM2K_MSGT_CON_CONF_RES: rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_CON_CONF_RES_ACK); break; + case OM2K_MSGT_MCTR_CONF_RES: + rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_MCTR_CONF_RES_ACK); + break; case OM2K_MSGT_TX_CONF_RES: rc = abis_om2k_tx_simple(bts, &o2h->mo, OM2K_MSGT_TX_CONF_RES_ACK); break; @@ -2830,6 +2905,7 @@ int abis_om2k_rcvmsg(struct msgb *msg) case OM2K_MSGT_TEST_REQ_REJ: case OM2K_MSGT_CON_CONF_REQ_REJ: case OM2K_MSGT_IS_CONF_REQ_REJ: + case OM2K_MSGT_MCTR_CONF_REQ_REJ: case OM2K_MSGT_TX_CONF_REQ_REJ: case OM2K_MSGT_RX_CONF_REQ_REJ: case OM2K_MSGT_TS_CONF_REQ_REJ: @@ -2910,6 +2986,8 @@ void abis_om2k_bts_init(struct gsm_bts *bts) bts->nr, 0xFF, 0); om2k_mo_init(&bts->rbs2000.tf.om2k_mo, OM2K_MO_CLS_TF, bts->nr, 0xFF, 0); + om2k_mo_init(&bts->rbs2000.mctr.om2k_mo, OM2K_MO_CLS_MCTR, + bts->nr, 0xFF, 0); // FIXME: There can be multiple MCTRs ... } static __attribute__((constructor)) void abis_om2k_init(void) -- cgit v1.2.3 From 94033ef9a76beec5ebaa5f7fda8d89a560add5ae Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 8 May 2020 09:59:23 +0200 Subject: om2k: Properly update the 'fake' 12.21 states using OM2000 status Signed-off-by: Sylvain Munaut Change-Id: I1caafa2e87c6198bf3b1a77f0fa1edc774deeef9 --- src/osmo-bsc/abis_om2000.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index 2380f5c8d..ae36ff28e 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -310,6 +310,13 @@ enum abis_om2k_dei { OM2K_DEI_MCTR_FEAT_STATUS_BMAP = 0xab, }; +enum abis_om2k_mostate { + OM2K_MOSTATE_RESET = 0x00, + OM2K_MOSTATE_STARTED = 0x01, + OM2K_MOSTATE_ENABLED = 0x02, + OM2K_MOSTATE_DISABLED = 0x03, +}; + const struct tlv_definition om2k_att_tlvdef = { .def = { [OM2K_DEI_ACCORDANCE_IND] = { TLV_TYPE_TV }, @@ -782,7 +789,6 @@ get_om2k_mo(struct gsm_bts *bts, const struct abis_om2k_mo *abis_mo) case OM2K_MO_CLS_MCTR: mo = &bts->rbs2000.mctr.om2k_mo; break; - case OM2K_MO_CLS_TRXC: trx = gsm_bts_trx_num(bts, abis_mo->inst); if (!trx) @@ -874,6 +880,9 @@ mo2nm_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo) return NULL; nm_state = &trx->ts[mo->inst].mo.nm_state; break; + case OM2K_MO_CLS_MCTR: + nm_state = &bts->rbs2000.mctr.mo.nm_state; + break; case OM2K_MO_CLS_TF: nm_state = &bts->rbs2000.tf.mo.nm_state; break; @@ -922,6 +931,7 @@ static void *mo2obj(struct gsm_bts *bts, struct abis_om2k_mo *mo) if (mo->inst >= ARRAY_SIZE(trx->ts)) return NULL; return &trx->ts[mo->inst]; + case OM2K_MO_CLS_MCTR: case OM2K_MO_CLS_TF: case OM2K_MO_CLS_IS: case OM2K_MO_CLS_CON: @@ -939,13 +949,39 @@ static void update_mo_state(struct gsm_bts *bts, struct abis_om2k_mo *mo, struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); struct gsm_nm_state new_state; struct nm_statechg_signal_data nsd; + bool has_enabled_state; if (!nm_state) return; + switch (mo->class) { + case OM2K_MO_CLS_CF: + case OM2K_MO_CLS_TRXC: + has_enabled_state = false; + break; + default: + has_enabled_state = true; + break; + } + new_state = *nm_state; - /* NOTICE: 12.21 Availability state values != OM2000 */ - new_state.availability = mo_state; + switch (mo_state) { + case OM2K_MOSTATE_RESET: + new_state.availability = NM_AVSTATE_POWER_OFF; + break; + case OM2K_MOSTATE_STARTED: + new_state.availability = has_enabled_state ? NM_AVSTATE_OFF_LINE : NM_AVSTATE_OK; + break; + case OM2K_MOSTATE_ENABLED: + new_state.availability = NM_AVSTATE_OK; + break; + case OM2K_MOSTATE_DISABLED: + new_state.availability = NM_AVSTATE_POWER_OFF; + break; + default: + new_state.availability = NM_AVSTATE_DEGRADED; + break; + } memset(&nsd, 0, sizeof(nsd)); -- cgit v1.2.3 From b405e6e3152fd75c4c72adf2d143d2b1f14faa68 Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Fri, 8 May 2020 11:50:46 +0200 Subject: om2k: Wait for OM TRX links to stabilize before trying to bring up TRX The OM2K link "per-trx" only comes up after MCTR is setup. So that means we need to wait for it before trying to boot the TRX itself. He we simply apply a "dumb" 5 sec timeout as this is the most reliable way I found to get this working reliably. Tracking the link state proved difficult and unreliable: - Multiple TRX can be present with their link coming up in random order. - They can already be up at the start (BTS already initialized from a previous boot) and so the link may actually come up, down, and up again. - All of theses transitions might happens before/after we get to the OM2K_BTS_S_WAIT_TRX state depending on how the LAPD timeout expire, if the BTS config was actually changed or not and how much time it takes to apply the new config. So all in all, what we must do is wait for the link to stabilize ... hence just waiting 5 second. Signed-off-by: Sylvain Munaut Change-Id: I55a06e08b9c52ff6e97e8c72f2d55770809eba51 --- src/osmo-bsc/abis_om2000.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index ae36ff28e..c69655732 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -76,6 +76,7 @@ struct osmo_fsm_inst *osmo_fsm_inst_alloc_child_id(struct osmo_fsm *fsm, #define OM_HEADROOM_SIZE 128 #define OM2K_TIMEOUT 10 +#define TRX_LAPD_TIMEOUT 5 #define TRX_FSM_TIMEOUT 60 #define BTS_FSM_TIMEOUT 60 @@ -2297,6 +2298,7 @@ enum om2k_bts_event { OM2K_BTS_EVT_CON_DONE, OM2K_BTS_EVT_TF_DONE, OM2K_BTS_EVT_MCTR_DONE, + OM2K_BTS_EVT_TRX_LAPD_UP, OM2K_BTS_EVT_TRX_DONE, OM2K_BTS_EVT_STOP, }; @@ -2308,6 +2310,7 @@ static const struct value_string om2k_bts_events[] = { { OM2K_BTS_EVT_CON_DONE, "CON-DONE" }, { OM2K_BTS_EVT_TF_DONE, "TF-DONE" }, { OM2K_BTS_EVT_MCTR_DONE, "MCTR-DONE" }, + { OM2K_BTS_EVT_TRX_LAPD_UP, "TRX-LAPD-UP" }, { OM2K_BTS_EVT_TRX_DONE, "TRX-DONE" }, { OM2K_BTS_EVT_STOP, "STOP" }, { 0, NULL } @@ -2320,6 +2323,7 @@ enum om2k_bts_state { OM2K_BTS_S_WAIT_CON, OM2K_BTS_S_WAIT_TF, OM2K_BTS_S_WAIT_MCTR, + OM2K_BTS_S_WAIT_TRX_LAPD, OM2K_BTS_S_WAIT_TRX, OM2K_BTS_S_DONE, OM2K_BTS_S_ERROR, @@ -2394,21 +2398,25 @@ static void om2k_bts_s_wait_is(struct osmo_fsm_inst *fi, uint32_t event, void *d om2k_mo_fsm_start(fi, OM2K_BTS_EVT_MCTR_DONE, bts->c0, &bts->rbs2000.mctr.om2k_mo); } else { - struct gsm_bts_trx *trx; - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX, - BTS_FSM_TIMEOUT, 0); - obfp->next_trx_nr = 0; - trx = gsm_bts_trx_num(obfp->bts, obfp->next_trx_nr++); - om2k_trx_fsm_start(fi, trx, OM2K_BTS_EVT_TRX_DONE); + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX_LAPD, + TRX_LAPD_TIMEOUT, 0); } } static void om2k_bts_s_wait_mctr(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + OSMO_ASSERT(event == OM2K_BTS_EVT_MCTR_DONE); + + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX_LAPD, + TRX_LAPD_TIMEOUT, 0); +} + +static void om2k_bts_s_wait_trx_lapd(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct om2k_bts_fsm_priv *obfp = fi->priv; struct gsm_bts_trx *trx; - OSMO_ASSERT(event == OM2K_BTS_EVT_MCTR_DONE); + OSMO_ASSERT(event == OM2K_BTS_EVT_TRX_LAPD_UP); osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_WAIT_TRX, BTS_FSM_TIMEOUT, 0); @@ -2469,17 +2477,23 @@ static const struct osmo_fsm_state om2k_bts_states[] = { .in_event_mask = S(OM2K_BTS_EVT_IS_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | S(OM2K_BTS_S_WAIT_MCTR) | - S(OM2K_BTS_S_WAIT_TRX), + S(OM2K_BTS_S_WAIT_TRX_LAPD), .name = "WAIT-IS", .action = om2k_bts_s_wait_is, }, [OM2K_BTS_S_WAIT_MCTR] = { .in_event_mask = S(OM2K_BTS_EVT_MCTR_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | - S(OM2K_BTS_S_WAIT_TRX), + S(OM2K_BTS_S_WAIT_TRX_LAPD), .name = "WAIT-MCTR", .action = om2k_bts_s_wait_mctr, }, + [OM2K_BTS_S_WAIT_TRX_LAPD] = { + .in_event_mask = S(OM2K_BTS_EVT_TRX_LAPD_UP), + .out_state_mask = S(OM2K_BTS_S_WAIT_TRX), + .name = "WAIT-TRX-LAPD", + .action = om2k_bts_s_wait_trx_lapd, + }, [OM2K_BTS_S_WAIT_TRX] = { .in_event_mask = S(OM2K_BTS_EVT_TRX_DONE), .out_state_mask = S(OM2K_BTS_S_ERROR) | @@ -2498,7 +2512,14 @@ static const struct osmo_fsm_state om2k_bts_states[] = { static int om2k_bts_timer_cb(struct osmo_fsm_inst *fi) { - osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_ERROR, 0, 0); + switch (fi->state) { + case OM2K_BTS_S_WAIT_TRX_LAPD: + osmo_fsm_inst_dispatch(fi, OM2K_BTS_EVT_TRX_LAPD_UP, NULL); + break; + default: + osmo_fsm_inst_state_chg(fi, OM2K_BTS_S_ERROR, 0, 0); + break; + } return 0; } -- cgit v1.2.3 From 241f058aeb3b714239887d3961b0ddd6829f75c1 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Wed, 6 May 2020 02:25:21 +0300 Subject: ctrs: Correctly count load total for dynamic timeslots. From the CS perspective, there is no difference whether this is a dynamic TS in NONE/PDCH mode or a static TCH in UNUSED mode since BSC can switch into USED mode at any moment. So we should count dynamic timeslots in the "total" count. A bit of a challenge here is that GSM_PCHAN_TCH_F_TCH_H_PDCH timeslots could be either switched to a single TCH/F or to two TCH/H, so the total can't be calculated reliably beforehand. In this code we assume TCH/F since this gives a lower total count. Change-Id: Iabd70e8adbf15eb3b7a7be597281ea99b352317b --- src/osmo-bsc/chan_alloc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c index 669eb8edb..ac246e0e7 100644 --- a/src/osmo-bsc/chan_alloc.c +++ b/src/osmo-bsc/chan_alloc.c @@ -58,6 +58,28 @@ void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts) if (!nm_is_running(&ts->mo.nm_state)) continue; + /* Dynamic timeslots have to be counted separately + * when not in TCH/F or TCH/H mode because they don't + * have an lchan's allocated to them. At the same time, + * dynamic timeslots in NONE and PDCH modes are same + * as in UNUSED mode from the CS channel load perspective + * beause they can be switched to TCH mode at any moment. + * I.e. they are "available" for TCH. */ + if ((ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH || + ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH) && + (ts->pchan_is == GSM_PCHAN_NONE || + ts->pchan_is == GSM_PCHAN_PDCH)) { + pl->total++; + } + + /* Count allocated logical channels. + * Note: A GSM_PCHAN_TCH_F_TCH_H_PDCH can be switched + * to a single TCH/F or to two TCH/H. So when it's in + * the TCH/H mode, total number of available channels + * is 1 more than when it's in the TCH/F mode. + * I.e. "total" count will fluctuate depending on + * whether GSM_PCHAN_TCH_F_TCH_H_PDCH timeslot is + * in TCH/F or TCH/H (or in NONE/PDCH) mode. */ ts_for_each_lchan(lchan, ts) { /* don't even count CBCH slots in total */ if (lchan->type == GSM_LCHAN_CBCH) -- cgit v1.2.3 From b091def16eb1044c5c87cdaa1569b8dff92eb3f1 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Wed, 6 May 2020 23:17:49 +0300 Subject: stats: Report per channel type load to statsd counters. Change-Id: I2eac4c93061204aeb8f3d223f7e78158c61c7156 --- include/osmocom/bsc/gsm_data.h | 16 ++++++++++++++ src/osmo-bsc/chan_alloc.c | 50 ++++++++++++++++++++++++++++++++++++++++++ src/osmo-bsc/gsm_data.c | 16 ++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 3fd466c3a..ecc1f0a06 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1453,6 +1453,22 @@ static const struct rate_ctr_group_desc bts_ctrg_desc = { enum { BTS_STAT_CHAN_LOAD_AVERAGE, + BTS_STAT_CHAN_CCCH_SDCCH4_USED, + BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL, + BTS_STAT_CHAN_TCH_F_USED, + BTS_STAT_CHAN_TCH_F_TOTAL, + BTS_STAT_CHAN_TCH_H_USED, + BTS_STAT_CHAN_TCH_H_TOTAL, + BTS_STAT_CHAN_SDCCH8_USED, + BTS_STAT_CHAN_SDCCH8_TOTAL, + BTS_STAT_CHAN_TCH_F_PDCH_USED, + BTS_STAT_CHAN_TCH_F_PDCH_TOTAL, + BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED, + BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL, + BTS_STAT_CHAN_SDCCH8_CBCH_USED, + BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL, + BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED, + BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL, BTS_STAT_T3122, BTS_STAT_RACH_BUSY, BTS_STAT_RACH_ACCESS, diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c index ac246e0e7..b2fbac881 100644 --- a/src/osmo-bsc/chan_alloc.c +++ b/src/osmo-bsc/chan_alloc.c @@ -109,6 +109,53 @@ void network_chan_load(struct pchan_load *pl, struct gsm_network *net) bts_chan_load(pl, bts); } +static void chan_load_stat_set(enum gsm_phys_chan_config pchan, + struct gsm_bts *bts, + struct load_counter *lc) +{ + switch (pchan) { + case GSM_PCHAN_NONE: + case GSM_PCHAN_CCCH: + case GSM_PCHAN_PDCH: + case GSM_PCHAN_UNKNOWN: + break; + case GSM_PCHAN_CCCH_SDCCH4: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_CCCH_SDCCH4_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_CCCH_SDCCH4_TOTAL], lc->total); + break; + case GSM_PCHAN_TCH_F: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_TOTAL], lc->total); + break; + case GSM_PCHAN_TCH_H: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_H_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_H_TOTAL], lc->total); + break; + case GSM_PCHAN_SDCCH8_SACCH8C: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_SDCCH8_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_SDCCH8_TOTAL], lc->total); + break; + case GSM_PCHAN_TCH_F_PDCH: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_PDCH_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_PDCH_TOTAL], lc->total); + break; + case GSM_PCHAN_CCCH_SDCCH4_CBCH: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_CCCH_SDCCH4_CBCH_TOTAL], lc->total); + break; + case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_SDCCH8_CBCH_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_SDCCH8_CBCH_TOTAL], lc->total); + break; + case GSM_PCHAN_TCH_F_TCH_H_PDCH: + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_USED], lc->used); + osmo_stat_item_set(bts->bts_statg->items[BTS_STAT_CHAN_TCH_F_TCH_H_PDCH_TOTAL], lc->total); + break; + default: + LOG_BTS(bts, DRLL, LOGL_NOTICE, "Unknown channel type %d\n", pchan); + } +} + /* Update T3122 wait indicator based on samples of BTS channel load. */ void bts_update_t3122_chan_load(struct gsm_bts *bts) @@ -133,6 +180,9 @@ bts_update_t3122_chan_load(struct gsm_bts *bts) for (i = 0; i < ARRAY_SIZE(pl.pchan); i++) { struct load_counter *lc = &pl.pchan[i]; + /* Export channel load to stats gauges */ + chan_load_stat_set(i, bts, lc); + /* Ignore samples too large for fixed-point calculations (shouldn't happen). */ if (lc->used > UINT16_MAX || lc->total > UINT16_MAX) { LOG_BTS(bts, DRLL, LOGL_NOTICE, "numbers in channel load sample " diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index fe421a4bf..8852efa7d 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -371,6 +371,22 @@ void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value) static const struct osmo_stat_item_desc bts_stat_desc[] = { { "chanloadavg", "Channel load average.", "%", 16, 0 }, + { "chan_ccch_sdcch4:used", "Number of CCCH+SDCCH4 channels used", "", 16, 0 }, + { "chan_ccch_sdcch4:total", "Number of CCCH+SDCCH4 channels total", "", 16, 0 }, + { "chan_tch_f:used", "Number of TCH/F channels used", "", 16, 0 }, + { "chan_tch_f:total", "Number of TCH/F channels total", "", 16, 0 }, + { "chan_tch_h:used", "Number of TCH/H channels used", "", 16, 0 }, + { "chan_tch_h:total", "Number of TCH/H channels total", "", 16, 0 }, + { "chan_sdcch8:used", "Number of SDCCH8 channels used", "", 16, 0 }, + { "chan_sdcch8:total", "Number of SDCCH8 channels total", "", 16, 0 }, + { "chan_tch_f_pdch:used", "Number of TCH/F_PDCH channels used", "", 16, 0 }, + { "chan_tch_f_pdch:total", "Number of TCH/F_PDCH channels total", "", 16, 0 }, + { "chan_ccch_sdcch4_cbch:used", "Number of CCCH+SDCCH4+CBCH channels used", "", 16, 0 }, + { "chan_ccch_sdcch4_cbch:total", "Number of CCCH+SDCCH4+CBCH channels total", "", 16, 0 }, + { "chan_sdcch8_cbch:used", "Number of SDCCH8+CBCH channels used", "", 16, 0 }, + { "chan_sdcch8_cbch:total", "Number of SDCCH8+CBCH channels total", "", 16, 0 }, + { "chan_tch_f_tch_h_pdch:used", "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 }, + { "chan_tch_f_tch_h_pdch:total", "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 }, { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator.", "s", 16, GSM_T3122_DEFAULT }, { "rach_busy", "RACH slots with signal above threshold", "%", 16, 0 }, { "rach_access", "RACH slots with access bursts in them", "%", 16, 0 }, -- cgit v1.2.3 From 669f87955d873249597f1fb69c7b8842293159c1 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 7 May 2020 16:17:24 +0300 Subject: stats: Remove dots from the end of stats descriptions. Change-Id: I4e66b3c864f6c54332fd6dabb0ec549c3590a1f2 --- src/osmo-bsc/gsm_data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index 8852efa7d..8b4cd4c41 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -370,7 +370,7 @@ void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value) } static const struct osmo_stat_item_desc bts_stat_desc[] = { - { "chanloadavg", "Channel load average.", "%", 16, 0 }, + { "chanloadavg", "Channel load average", "%", 16, 0 }, { "chan_ccch_sdcch4:used", "Number of CCCH+SDCCH4 channels used", "", 16, 0 }, { "chan_ccch_sdcch4:total", "Number of CCCH+SDCCH4 channels total", "", 16, 0 }, { "chan_tch_f:used", "Number of TCH/F channels used", "", 16, 0 }, @@ -387,7 +387,7 @@ static const struct osmo_stat_item_desc bts_stat_desc[] = { { "chan_sdcch8_cbch:total", "Number of SDCCH8+CBCH channels total", "", 16, 0 }, { "chan_tch_f_tch_h_pdch:used", "Number of TCH/F_TCH/H_PDCH channels used", "", 16, 0 }, { "chan_tch_f_tch_h_pdch:total", "Number of TCH/F_TCH/H_PDCH channels total", "", 16, 0 }, - { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator.", "s", 16, GSM_T3122_DEFAULT }, + { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator", "s", 16, GSM_T3122_DEFAULT }, { "rach_busy", "RACH slots with signal above threshold", "%", 16, 0 }, { "rach_access", "RACH slots with access bursts in them", "%", 16, 0 }, }; -- cgit v1.2.3 From 94b57850fde672b4b00b620ebce39134d0e8af64 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 7 May 2020 16:41:26 +0300 Subject: stats: Add a stats gauge for the MSC links count. Change-Id: Ibe4b29056ba704a27b925cfdba49f343ee34f428 --- include/osmocom/bsc/bsc_msc_data.h | 10 ++++++++++ src/osmo-bsc/a_reset.c | 37 +++++++++++++++++++++++++++++++------ src/osmo-bsc/osmo_bsc_msc.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h index b9df4ba8f..7d797eb9e 100644 --- a/include/osmocom/bsc/bsc_msc_data.h +++ b/include/osmocom/bsc/bsc_msc_data.h @@ -56,6 +56,12 @@ enum { MSC_CON_TYPE_LOCAL, }; +/* Constants for the MSC stats */ +enum { + MSC_STAT_MSC_LINKS_ACTIVE, + MSC_STAT_MSC_LINKS_TOTAL, +}; + /*! /brief Information on a remote MSC for libbsc. */ struct bsc_msc_data { @@ -99,6 +105,10 @@ struct bsc_msc_data { char *acc_lst_name; + /* structures for keeping rate counters and gauge stats */ + struct rate_ctr_group *msc_ctrs; + struct osmo_stat_item_group *msc_statg; + /* Sigtran connection data */ struct { uint32_t cs7_instance; diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c index 3f512781b..63273e9f2 100644 --- a/src/osmo-bsc/a_reset.c +++ b/src/osmo-bsc/a_reset.c @@ -66,18 +66,28 @@ static const struct value_string fsm_event_names[] = { {0, NULL} }; -/* Disconnected state */ +/* Disconnected state event handler */ static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv; OSMO_ASSERT(reset_ctx); - LOGPFSML(fi, LOGL_NOTICE, "SIGTRAN connection succeeded.\n"); reset_ctx->conn_loss_counter = 0; osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0); } -/* Connected state */ +/* Called when entering Disconnected state */ +static void fsm_disc_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv; + struct bsc_msc_data *msc = reset_ctx->priv; + + LOGPFSML(fi, LOGL_NOTICE, "SIGTRAN connection down, reconnecting...\n"); + if (prev_state != ST_DISC) + osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1); +} + +/* Connected state event handler */ static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) { struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv; @@ -85,10 +95,9 @@ static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) switch (event) { case EV_N_DISCONNECT: - if (reset_ctx->conn_loss_counter >= BAD_CONNECTION_THRESOLD) { - LOGPFSML(fi, LOGL_NOTICE, "SIGTRAN connection down, reconnecting...\n"); + if (reset_ctx->conn_loss_counter >= BAD_CONNECTION_THRESOLD) osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO); - } else + else reset_ctx->conn_loss_counter++; break; case EV_N_CONNECT: @@ -97,6 +106,17 @@ static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data) } } +/* Called when entering Connected state */ +static void fsm_conn_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv; + struct bsc_msc_data *msc = reset_ctx->priv; + + LOGPFSML(fi, LOGL_NOTICE, "SIGTRAN connection succeeded.\n"); + if (prev_state != ST_CONN) + osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1); +} + /* Timer callback to retransmit the reset signal */ static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi) { @@ -117,12 +137,14 @@ static struct osmo_fsm_state reset_fsm_states[] = { .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN), .name = "DISC", .action = fsm_disc_cb, + .onenter = fsm_disc_onenter_cb, }, [ST_CONN] = { .in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT), .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN), .name = "CONN", .action = fsm_conn_cb, + .onenter = fsm_conn_onenter_cb, }, }; @@ -161,6 +183,9 @@ void a_reset_alloc(struct bsc_msc_data *msc, const char *name, void *cb) /* Immediately (1ms) kick off reset sending mechanism */ osmo_fsm_inst_state_chg_ms(reset_fsm, ST_DISC, 1, RESET_RESEND_TIMER_NO); + + /* Count the new MSC link */ + osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_TOTAL], 1); } /* Confirm that we successfully received a reset acknowledge message */ diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c index 24c8c6d99..1704a73a8 100644 --- a/src/osmo-bsc/osmo_bsc_msc.c +++ b/src/osmo-bsc/osmo_bsc_msc.c @@ -43,6 +43,30 @@ #include #include +static const struct rate_ctr_desc msc_ctr_description[] = { +}; + +static const struct rate_ctr_group_desc msc_ctrg_desc = { + "msc", + "mobile switching center", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(msc_ctr_description), + msc_ctr_description, +}; + +static const struct osmo_stat_item_desc msc_stat_desc[] = { + { "msc_links:active", "Number of active MSC links", "", 16, 0 }, + { "msc_links:total", "Number of configured MSC links", "", 16, 0 }, +}; + +static const struct osmo_stat_item_group_desc msc_statg_desc = { + .group_name_prefix = "msc", + .group_description = "mobile switching center", + .class_id = OSMO_STATS_CLASS_GLOBAL, + .num_items = ARRAY_SIZE(msc_stat_desc), + .item_desc = msc_stat_desc, +}; + int osmo_bsc_msc_init(struct bsc_msc_data *msc) { struct gsm_network *net = msc->network; @@ -91,6 +115,19 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr) if (!msc_data) return NULL; + /* init statistics */ + msc_data->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, nr); + if (!msc_data->msc_ctrs) { + talloc_free(msc_data); + return NULL; + } + msc_data->msc_statg = osmo_stat_item_group_alloc(net, &msc_statg_desc, nr); + if (!msc_data->msc_statg) { + rate_ctr_group_free(msc_data->msc_ctrs); + talloc_free(msc_data); + return NULL; + } + llist_add_tail(&msc_data->entry, &net->bsc_data->mscs); /* Init back pointer */ -- cgit v1.2.3 From d63f982102f94ead49e745d62d713efba00958a8 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 01:46:30 +0300 Subject: stats: Fix stat group index for BTS stats. osmo_stat_item_group_alloc() should be initialized with the BTS number. Change-Id: Iedef08af56ab6985894d89ff7b285246424ca9e7 --- src/osmo-bsc/gsm_data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index 8b4cd4c41..23a4e61b3 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -832,7 +832,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num) talloc_free(bts); return NULL; } - bts->bts_statg = osmo_stat_item_group_alloc(bts, &bts_statg_desc, 0); + bts->bts_statg = osmo_stat_item_group_alloc(bts, &bts_statg_desc, bts->nr); /* create our primary TRX */ bts->c0 = gsm_bts_trx_alloc(bts); -- cgit v1.2.3 From 9cb752c1c493afed2c82aac385a0112c37efd05d Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 01:49:12 +0300 Subject: stats: report a number of configured BTS to a stats gauge. It's useful to know how many BTS are actually configured to compare it to a number of connected BTS's. Change-Id: I41cb60f9cb962003227e4a7b63db05acbcdb6f4c --- include/osmocom/bsc/gsm_data.h | 7 +++++++ src/osmo-bsc/bsc_init.c | 18 ++++++++++++++++++ src/osmo-bsc/bsc_vty.c | 1 + 3 files changed, 26 insertions(+) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index ecc1f0a06..f84520973 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1562,6 +1562,11 @@ static const struct rate_ctr_group_desc bsc_ctrg_desc = { bsc_ctr_description, }; +/* Constants for the BSC stats */ +enum { + BSC_STAT_NUM_BTS_TOTAL, +}; + struct gsm_tz { int override; /* if 0, use system's time zone instead. */ int hr; /* hour */ @@ -1588,7 +1593,9 @@ struct gsm_network { struct osmo_timer_list congestion_check_timer; } hodec2; + /* structures for keeping rate counters and gauge stats */ struct rate_ctr_group *bsc_ctrs; + struct osmo_stat_item_group *bsc_statg; unsigned int num_bts; struct llist_head bts_list; diff --git a/src/osmo-bsc/bsc_init.c b/src/osmo-bsc/bsc_init.c index 18776f33d..d08e9c861 100644 --- a/src/osmo-bsc/bsc_init.c +++ b/src/osmo-bsc/bsc_init.c @@ -44,6 +44,18 @@ #include #include +static const struct osmo_stat_item_desc bsc_stat_desc[] = { + { "num_bts:total", "Number of configured BTS for this BSC", "", 16, 0 }, +}; + +static const struct osmo_stat_item_group_desc bsc_statg_desc = { + .group_name_prefix = "bsc", + .group_description = "base station controller", + .class_id = OSMO_STATS_CLASS_GLOBAL, + .num_items = ARRAY_SIZE(bsc_stat_desc), + .item_desc = bsc_stat_desc, +}; + int bsc_shutdown_net(struct gsm_network *net) { struct gsm_bts *bts; @@ -268,6 +280,12 @@ static struct gsm_network *bsc_network_init(void *ctx) talloc_free(net); return NULL; } + net->bsc_statg = osmo_stat_item_group_alloc(net, &bsc_statg_desc, 0); + if (!net->bsc_statg) { + rate_ctr_group_free(net->bsc_ctrs); + talloc_free(net); + return NULL; + } INIT_LLIST_HEAD(&net->bts_rejected); gsm_net_update_ctype(net); diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index f8bcee9a7..0fd462f33 100644 --- a/src/osmo-bsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -2077,6 +2077,7 @@ DEFUN(cfg_bts, /* allocate a new one */ bts = bsc_bts_alloc_register(gsmnet, GSM_BTS_TYPE_UNKNOWN, HARDCODED_BSIC); + osmo_stat_item_inc(gsmnet->bsc_statg->items[BSC_STAT_NUM_BTS_TOTAL], 1); /* * Initialize bts->acc_ramp here. Else we could segfault while * processing a configuration file with ACC ramping settings. -- cgit v1.2.3 From 8671e52f7cfb6b236cf61d71758d5dd44d99c85e Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 01:51:35 +0300 Subject: Fix a comment for the handle_unitdata_from_msc() function. Change-Id: If20632cfe63b78c2cb17c1bb9d12207a4956be64 --- src/osmo-bsc/osmo_bsc_sigtran.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c index 50b03ce47..08efae4be 100644 --- a/src/osmo-bsc/osmo_bsc_sigtran.c +++ b/src/osmo-bsc/osmo_bsc_sigtran.c @@ -143,14 +143,14 @@ static struct bsc_msc_data *get_msc_by_addr(const struct osmo_sccp_addr *msc_add return NULL; } -/* Send data to MSC, use the connection id which MSC it is */ +/* Received data from MSC, use the connection id which MSC it is */ static int handle_data_from_msc(struct gsm_subscriber_connection *conn, struct msgb *msg) { msg->l3h = msgb_l2(msg); return bsc_handle_dt(conn, msg, msgb_l2len(msg)); } -/* Sent unitdata to MSC, use the point code to determine which MSC it is */ +/* Received unitdata from MSC, use the point code to determine which MSC it is */ static int handle_unitdata_from_msc(const struct osmo_sccp_addr *msc_addr, struct msgb *msg, const struct osmo_sccp_user *scu) { -- cgit v1.2.3 From db1ecbd1c8185bd4c742b44980cc24d831640a4e Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 02:37:01 +0300 Subject: Fix indent whitespace and log message. Change-Id: I985bf8ac4ce6136812692c06b6dc78edc6bde652 --- src/osmo-bsc/osmo_bsc_bssap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c index 1ba490faa..e79ce9de6 100644 --- a/src/osmo-bsc/osmo_bsc_bssap.c +++ b/src/osmo-bsc/osmo_bsc_bssap.c @@ -1102,14 +1102,14 @@ static int dtap_rcvmsg(struct gsm_subscriber_connection *conn, header = (struct dtap_header *) msg->l3h; if (sizeof(*header) >= length) { - LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %zu got: %u\n", sizeof(*header), length); - LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length)); - return -1; + LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %zu got: %u, hex: %s\n", + sizeof(*header), length, osmo_hexdump(msg->l3h, length)); + return -1; } if (header->length > length - sizeof(*header)) { - LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit: header: %u length: %u\n", header->length, length); - LOGP(DMSC, LOGL_ERROR, "hex: %s\n", osmo_hexdump(msg->l3h, length)); + LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit. Wanted: %u got: %zu, hex: %s\n", + header->length, length - sizeof(*header), osmo_hexdump(msg->l3h, length)); return -1; } -- cgit v1.2.3 From f1a1d7c34f9d203c5e3a514fa7a32b06586aa70a Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 02:37:47 +0300 Subject: stats: Add counters for received BSSMAP messages. Change-Id: I3f08d71b58b4e8d6f61376d85c2051e194aa8e43 --- include/osmocom/bsc/bsc_msc_data.h | 17 +++++++++++++++++ src/osmo-bsc/osmo_bsc_bssap.c | 17 +++++++++++++++++ src/osmo-bsc/osmo_bsc_msc.c | 13 +++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h index 7d797eb9e..dc9628bd1 100644 --- a/include/osmocom/bsc/bsc_msc_data.h +++ b/include/osmocom/bsc/bsc_msc_data.h @@ -56,6 +56,23 @@ enum { MSC_CON_TYPE_LOCAL, }; +/* Constants for the MSC rate counters */ +enum { + MSC_CTR_BSSMAP_RX_UDT_RESET_ACKNOWLEDGE, + MSC_CTR_BSSMAP_RX_UDT_RESET, + MSC_CTR_BSSMAP_RX_UDT_PAGING, + MSC_CTR_BSSMAP_RX_UDT_UNKNOWN, + MSC_CTR_BSSMAP_RX_DT1_CLEAR_CMD, + MSC_CTR_BSSMAP_RX_DT1_CIPHER_MODE_CMD, + MSC_CTR_BSSMAP_RX_DT1_ASSIGMENT_RQST, + MSC_CTR_BSSMAP_RX_DT1_LCLS_CONNECT_CTRL, + MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD, + MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST, + MSC_CTR_BSSMAP_RX_DT1_UNKNOWN, + MSC_CTR_BSSMAP_RX_DTAP_MSG, + MSC_CTR_BSSMAP_RX_DTAP_ERROR, +}; + /* Constants for the MSC stats */ enum { MSC_STAT_MSC_LINKS_ACTIVE, diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c index e79ce9de6..f1e43be5a 100644 --- a/src/osmo-bsc/osmo_bsc_bssap.c +++ b/src/osmo-bsc/osmo_bsc_bssap.c @@ -1007,6 +1007,7 @@ static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc, struct msgb *msg, unsigned int length) { int ret = 0; + struct rate_ctr *ctrs = msc->msc_ctrs->ctr; if (length < 1) { LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length); @@ -1018,15 +1019,19 @@ static int bssmap_rcvmsg_udt(struct bsc_msc_data *msc, switch (msg->l4h[0]) { case BSS_MAP_MSG_RESET_ACKNOWLEDGE: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_UDT_RESET_ACKNOWLEDGE]); ret = bssmap_handle_reset_ack(msc, msg, length); break; case BSS_MAP_MSG_RESET: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_UDT_RESET]); ret = bssmap_handle_reset(msc, msg, length); break; case BSS_MAP_MSG_PAGING: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_UDT_PAGING]); ret = bssmap_handle_paging(msc, msg, length); break; default: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_UDT_UNKNOWN]); LOGP(DMSC, LOGL_NOTICE, "Received unimplemented BSSMAP UDT %s\n", gsm0808_bssmap_name(msg->l4h[0])); break; @@ -1039,6 +1044,7 @@ static int bssmap_rcvmsg_dt1(struct gsm_subscriber_connection *conn, struct msgb *msg, unsigned int length) { int ret = 0; + struct rate_ctr *ctrs = conn->sccp.msc->msc_ctrs->ctr; if (length < 1) { LOGP(DMSC, LOGL_ERROR, "Not enough room: %d\n", length); @@ -1050,24 +1056,31 @@ static int bssmap_rcvmsg_dt1(struct gsm_subscriber_connection *conn, switch (msg->l4h[0]) { case BSS_MAP_MSG_CLEAR_CMD: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_CLEAR_CMD]); ret = bssmap_handle_clear_cmd(conn, msg, length); break; case BSS_MAP_MSG_CIPHER_MODE_CMD: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_CIPHER_MODE_CMD]); ret = bssmap_handle_cipher_mode(conn, msg, length); break; case BSS_MAP_MSG_ASSIGMENT_RQST: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_ASSIGMENT_RQST]); ret = bssmap_handle_assignm_req(conn, msg, length); break; case BSS_MAP_MSG_LCLS_CONNECT_CTRL: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_LCLS_CONNECT_CTRL]); ret = bssmap_handle_lcls_connect_ctrl(conn, msg, length); break; case BSS_MAP_MSG_HANDOVER_CMD: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD]); ret = bssmap_handle_handover_cmd(conn, msg, length); break; case BSS_MAP_MSG_CLASSMARK_RQST: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST]); ret = gsm48_send_rr_classmark_enquiry(conn->lchan); break; default: + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DT1_UNKNOWN]); LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n", gsm0808_bssmap_name(msg->l4h[0])); break; @@ -1091,6 +1104,7 @@ static int dtap_rcvmsg(struct gsm_subscriber_connection *conn, struct msgb *gsm48; uint8_t *data; int rc, dtap_rc; + struct rate_ctr *ctrs = conn->sccp.msc->msc_ctrs->ctr; LOGP(DMSC, LOGL_DEBUG, "Rx MSC DTAP: %s\n", osmo_hexdump(msg->l3h, length)); @@ -1102,17 +1116,20 @@ static int dtap_rcvmsg(struct gsm_subscriber_connection *conn, header = (struct dtap_header *) msg->l3h; if (sizeof(*header) >= length) { + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DTAP_ERROR]); LOGP(DMSC, LOGL_ERROR, "The DTAP header does not fit. Wanted: %zu got: %u, hex: %s\n", sizeof(*header), length, osmo_hexdump(msg->l3h, length)); return -1; } if (header->length > length - sizeof(*header)) { + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DTAP_ERROR]); LOGP(DMSC, LOGL_ERROR, "The DTAP l4 information does not fit. Wanted: %u got: %zu, hex: %s\n", header->length, length - sizeof(*header), osmo_hexdump(msg->l3h, length)); return -1; } + rate_ctr_inc(&ctrs[MSC_CTR_BSSMAP_RX_DTAP_MSG]); LOGP(DMSC, LOGL_INFO, "Rx MSC DTAP, SAPI: %u CHAN: %u\n", header->link_id & 0x07, header->link_id & 0xC0); /* forward the data */ diff --git a/src/osmo-bsc/osmo_bsc_msc.c b/src/osmo-bsc/osmo_bsc_msc.c index 1704a73a8..d4d7bec1f 100644 --- a/src/osmo-bsc/osmo_bsc_msc.c +++ b/src/osmo-bsc/osmo_bsc_msc.c @@ -44,6 +44,19 @@ #include static const struct rate_ctr_desc msc_ctr_description[] = { + [MSC_CTR_BSSMAP_RX_UDT_RESET_ACKNOWLEDGE] = {"bssmap:rx_udt_reset_acknowledge", "Number of received BSSMAP UDT RESET ACKNOWLEDGE messages"}, + [MSC_CTR_BSSMAP_RX_UDT_RESET] = {"bssmap:rx_udt_reset", "Number of received BSSMAP UDT RESET messages"}, + [MSC_CTR_BSSMAP_RX_UDT_PAGING] = {"bssmap:rx_udt_paging", "Number of received BSSMAP UDT PAGING messages"}, + [MSC_CTR_BSSMAP_RX_UDT_UNKNOWN] = {"bssmap:rx_udt_unknown", "Number of received BSSMAP unknown UDT messages"}, + [MSC_CTR_BSSMAP_RX_DT1_CLEAR_CMD] = {"bssmap:rx_dt1_clear_cmd", "Number of received BSSMAP DT1 CLEAR CMD messages"}, + [MSC_CTR_BSSMAP_RX_DT1_CIPHER_MODE_CMD] = {"bssmap:rx_dt1_cipher_mode_cmd", "Number of received BSSMAP DT1 CIPHER MODE CMD messages"}, + [MSC_CTR_BSSMAP_RX_DT1_ASSIGMENT_RQST] = {"bssmap:rx_dt1_assignment_rqst", "Number of received BSSMAP DT1 ASSIGMENT RQST messages"}, + [MSC_CTR_BSSMAP_RX_DT1_LCLS_CONNECT_CTRL] = {"bssmap:rx_dt1_lcls_connect_ctrl", "Number of received BSSMAP DT1 LCLS CONNECT CTRL messages"}, + [MSC_CTR_BSSMAP_RX_DT1_HANDOVER_CMD] = {"bssmap:rx_dt1_handover_cmd", "Number of received BSSMAP DT1 HANDOVER CMD messages"}, + [MSC_CTR_BSSMAP_RX_DT1_CLASSMARK_RQST] = {"bssmap:rx_dt1_classmark_rqst", "Number of received BSSMAP DT1 CLASSMARK RQST messages"}, + [MSC_CTR_BSSMAP_RX_DT1_UNKNOWN] = {"bssmap:rx_dt1_unknown", "Number of received BSSMAP unknown DT1 messages"}, + [MSC_CTR_BSSMAP_RX_DTAP_MSG] = {"bssmap:rx_dtap_msg", "Number of received BSSMAP DTAP messages"}, + [MSC_CTR_BSSMAP_RX_DTAP_ERROR] = {"bssmap:rx_dtap_error", "Number of received BSSMAP DATP messages with errors"}, }; static const struct rate_ctr_group_desc msc_ctrg_desc = { -- cgit v1.2.3 From 28cb83ef8f7e817866c69b42de265119694b3f8f Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 7 May 2020 16:46:47 +0300 Subject: stats: Export connected OML/RSL links count per BTS. Change-Id: I88c8025940a0eecb034b1c70f76ea17937fa0325 --- include/osmocom/bsc/gsm_data.h | 2 ++ src/osmo-bsc/bts_ipaccess_nanobts.c | 4 ++++ src/osmo-bsc/gsm_data.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index f84520973..5e4b532c5 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1472,6 +1472,8 @@ enum { BTS_STAT_T3122, BTS_STAT_RACH_BUSY, BTS_STAT_RACH_ACCESS, + BTS_STAT_OML_CONNECTED, + BTS_STAT_RSL_CONNECTED, }; enum { diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c index a5e697be1..f004c1598 100644 --- a/src/osmo-bsc/bts_ipaccess_nanobts.c +++ b/src/osmo-bsc/bts_ipaccess_nanobts.c @@ -397,6 +397,7 @@ void ipaccess_drop_rsl(struct gsm_bts_trx *trx, const char *reason) LOG_TRX(trx, DLINP, LOGL_NOTICE, "Dropping RSL link: %s\n", reason); e1inp_sign_link_destroy(trx->rsl_link); trx->rsl_link = NULL; + osmo_stat_item_dec(trx->bts->bts_statg->items[BTS_STAT_RSL_CONNECTED], 1); if (trx->bts->c0 == trx) paging_flush_bts(trx->bts, NULL); @@ -417,6 +418,7 @@ void ipaccess_drop_oml(struct gsm_bts *bts, const char *reason) e1inp_sign_link_destroy(bts->oml_link); bts->oml_link = NULL; bts->uptime = 0; + osmo_stat_item_dec(bts->bts_statg->items[BTS_STAT_OML_CONNECTED], 1); /* we have issues reconnecting RSL, drop everything. */ llist_for_each_entry(trx, &bts->trx_list, list) @@ -558,6 +560,7 @@ ipaccess_sign_link_up(void *unit_data, struct e1inp_line *line, sign_link->tei, sign_link->sapi); sign_link->trx->bts->ip_access.flags |= OML_UP; } + osmo_stat_item_inc(bts->bts_statg->items[BTS_STAT_OML_CONNECTED], 1); break; case E1INP_SIGN_RSL: { struct e1inp_ts *ts; @@ -585,6 +588,7 @@ ipaccess_sign_link_up(void *unit_data, struct e1inp_line *line, sign_link->trx->bts->ip_access.flags |= (RSL_UP << sign_link->trx->nr); } + osmo_stat_item_inc(bts->bts_statg->items[BTS_STAT_RSL_CONNECTED], 1); break; } default: diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index 23a4e61b3..8b50805e3 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -390,6 +390,8 @@ static const struct osmo_stat_item_desc bts_stat_desc[] = { { "T3122", "T3122 IMMEDIATE ASSIGNMENT REJECT wait indicator", "s", 16, GSM_T3122_DEFAULT }, { "rach_busy", "RACH slots with signal above threshold", "%", 16, 0 }, { "rach_access", "RACH slots with access bursts in them", "%", 16, 0 }, + { "oml_connected", "Number of OML links connected", "", 16, 0 }, + { "rsl_connected", "Number of RSL links connected", "", 16, 0 }, }; static const struct osmo_stat_item_group_desc bts_statg_desc = { -- cgit v1.2.3 From f24d7c8ad0b2580d4ad1207b46639cb8e114acd0 Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Thu, 7 May 2020 15:32:52 +0300 Subject: chan_alloc: Add comments for the *_chan_load() functions. Change-Id: Ie199104fd4a6c0d5218f56b958d12fac4612fd78 --- src/osmo-bsc/chan_alloc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/osmo-bsc/chan_alloc.c b/src/osmo-bsc/chan_alloc.c index b2fbac881..75cea7162 100644 --- a/src/osmo-bsc/chan_alloc.c +++ b/src/osmo-bsc/chan_alloc.c @@ -37,6 +37,7 @@ #include +/* Update channel load calculation for the given BTS */ void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts) { struct gsm_bts_trx *trx; @@ -99,6 +100,7 @@ void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts) } } +/* Update channel load calculation for all BTS in the BSC */ void network_chan_load(struct pchan_load *pl, struct gsm_network *net) { struct gsm_bts *bts; -- cgit v1.2.3 From f103cd38665618442196de888b1e4390fb256ddb Mon Sep 17 00:00:00 2001 From: Alexander Chemeris Date: Fri, 8 May 2020 22:47:17 +0300 Subject: osmo_bsc_sigtran: Fix a SSCP-> SCCP typo in a comment Change-Id: Iee7e87922f2aa034840993b4bfad3de8defbf5f1 --- src/osmo-bsc/osmo_bsc_sigtran.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c index 08efae4be..e4530bfd1 100644 --- a/src/osmo-bsc/osmo_bsc_sigtran.c +++ b/src/osmo-bsc/osmo_bsc_sigtran.c @@ -215,7 +215,7 @@ refuse: return rc; } -/* Callback function, called by the SSCP stack when data arrives */ +/* Callback function, called by the SCCP stack when data arrives */ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu) { struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph; -- cgit v1.2.3