fix dyn TS init: properly identify BTS on OML OPSTART ACK

Commit "dyn ts, bts_ipaccess_nanobts.c: init PDCH on Chan OPSTART ACK"
bf7099262a Icf6e25ff068e8a2600562d52726ead65e864ec02
introduced signal S_NM_OPSTART_ACK and passed the FOM header to identify the BTS
by. But the FOM header's BTS number is zero on each Abis/IP link, and the BTS
and TRX are actually identified by msgb->dst == e1inp_sign_link, member trx. So
the initial implementation associated *all* Channel OPSTART ACKs with BTS 0.

Pass the entire msgb as S_NM_OPSTART_ACK signal argument, implement a
abis_nm_get_ts() to retrieve the proper timeslot and use that during timeslot
init.

Related: OS#3351 OS#3205
Change-Id: I45ce5c24cb62d00f350df1af1be6c11104d74193
This commit is contained in:
Neels Hofmeyr 2018-06-15 20:39:58 +02:00
parent e7d29e34e4
commit f0ff9a6711
4 changed files with 37 additions and 27 deletions

View File

@ -171,4 +171,6 @@ int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw, const size_t len)
/* Helper functions for updating attributes */ /* Helper functions for updating attributes */
int abis_nm_update_max_power_red(struct gsm_bts_trx *trx); int abis_nm_update_max_power_red(struct gsm_bts_trx *trx);
struct gsm_bts_trx_ts *abis_nm_get_ts(const struct msgb *oml_msg);
#endif /* _NM_H */ #endif /* _NM_H */

View File

@ -71,7 +71,7 @@ enum signal_nm {
S_NM_STATECHG_OPER, /* Operational State changed*/ S_NM_STATECHG_OPER, /* Operational State changed*/
S_NM_STATECHG_ADM, /* Administrative State changed */ S_NM_STATECHG_ADM, /* Administrative State changed */
S_NM_OM2K_CONF_RES, /* OM2K Configuration Result */ S_NM_OM2K_CONF_RES, /* OM2K Configuration Result */
S_NM_OPSTART_ACK, /* Received OPSTART ACK, arg is struct abis_om_fom_hdr* */ S_NM_OPSTART_ACK, /* Received OPSTART ACK, arg is struct msgb *oml_msg */
}; };
/* SS_LCHAN signals */ /* SS_LCHAN signals */

View File

@ -671,11 +671,36 @@ static int abis_nm_rx_lmt_event(struct msgb *mb)
return 0; return 0;
} }
/* From a received OML message, determine the matching struct gsm_bts_trx_ts instance.
* Note that the BTS-TRX-TS numbers received in the FOM header do not correspond to the local bts->nr and
* bts->trx->nr. Rather, the trx is identified by the e1inp_sign_link* found in msg->dst, and the TS is
* then obtained by the FOM header's TS number. */
struct gsm_bts_trx_ts *abis_nm_get_ts(const struct msgb *oml_msg)
{
struct abis_om_fom_hdr *foh = msgb_l3(oml_msg);
struct e1inp_sign_link *sign_link = oml_msg->dst;
struct gsm_bts_trx *trx = sign_link->trx;
uint8_t ts_nr = foh->obj_inst.ts_nr;
if (!trx) {
LOGP(DNM, LOGL_ERROR, "%s Channel OPSTART ACK for sign_link without trx\n",
abis_nm_dump_foh(foh));
return NULL;
}
if (ts_nr >= ARRAY_SIZE(trx->ts)) {
LOGP(DNM, LOGL_ERROR, "bts%u-trx%u %s Channel OPSTART ACK for non-existent TS\n",
trx->bts->nr, trx->nr, abis_nm_dump_foh(foh));
return NULL;
}
return &trx->ts[ts_nr];
}
static int abis_nm_rx_opstart_ack(struct msgb *mb) static int abis_nm_rx_opstart_ack(struct msgb *mb)
{ {
struct abis_om_fom_hdr *foh = msgb_l3(mb); struct abis_om_fom_hdr *foh = msgb_l3(mb);
DEBUGPFOH(DNM, foh, "Opstart ACK\n"); struct e1inp_sign_link *sign_link = mb->dst;
osmo_signal_dispatch(SS_NM, S_NM_OPSTART_ACK, foh); struct gsm_bts_trx *trx = sign_link->trx;
DEBUGPFOH(DNM, foh, "bts=%u trx=%u Opstart ACK\n", trx->bts->nr, trx->nr);
osmo_signal_dispatch(SS_NM, S_NM_OPSTART_ACK, mb);
return 0; return 0;
} }

View File

@ -298,40 +298,23 @@ static int sw_activ_rep(struct msgb *mb)
return 0; return 0;
} }
static struct gsm_bts_trx_ts *gsm_bts_trx_ts(struct gsm_network *net, static void nm_rx_opstart_ack_chan(struct msgb *oml_msg)
int bts_nr, int trx_nr, int ts_nr)
{
struct gsm_bts *bts;
struct gsm_bts_trx *trx;
bts = gsm_bts_num(net, bts_nr);
if (!bts)
return NULL;
trx = gsm_bts_trx_by_nr(bts, trx_nr);
if (!trx)
return NULL;
if (ts_nr < 0 || ts_nr > ARRAY_SIZE(trx->ts))
return NULL;
return &trx->ts[ts_nr];
}
static void nm_rx_opstart_ack_chan(struct abis_om_fom_hdr *foh)
{ {
struct gsm_bts_trx_ts *ts; struct gsm_bts_trx_ts *ts;
ts = gsm_bts_trx_ts(bsc_gsmnet, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr, foh->obj_inst.ts_nr); ts = abis_nm_get_ts(oml_msg);
if (!ts) { if (!ts)
LOGP(DNM, LOGL_ERROR, "%s Channel OPSTART ACK for non-existent TS\n", /* error already logged in abis_nm_get_ts() */
abis_nm_dump_foh(foh));
return; return;
}
gsm_ts_check_init(ts); gsm_ts_check_init(ts);
} }
static void nm_rx_opstart_ack(struct abis_om_fom_hdr *foh) static void nm_rx_opstart_ack(struct msgb *oml_msg)
{ {
struct abis_om_fom_hdr *foh = msgb_l3(oml_msg);
switch (foh->obj_class) { switch (foh->obj_class) {
case NM_OC_CHANNEL: case NM_OC_CHANNEL:
nm_rx_opstart_ack_chan(foh); nm_rx_opstart_ack_chan(oml_msg);
break; break;
default: default:
break; break;