int e1_reconfig_bts(struct gsm_bts *bts) { struct gsm_e1_subslot *e1_link = &bts->oml_e1_link; struct e1inp_ts *sign_ts; struct e1inp_line *line; struct e1inp_sign_link *oml_link; struct gsm_bts_trx *trx; struct timespec tp; int rc; DEBUGP(DLMI, "e1_reconfig_bts(%u)\n", bts->nr); 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; } if (!bts->model->e1line_bind_ops) { LOGP(DLINP, LOGL_ERROR, "no callback to bind E1 line operations\n"); return -EINVAL; } if (!line->ops) bts->model->e1line_bind_ops(line); /* skip signal link initialization, this is done later for these BTS. */ if (bts->type == GSM_BTS_TYPE_NANOBTS || bts->type == GSM_BTS_TYPE_OSMOBTS) return e1inp_line_update(line); /* OML link */ if (!e1_link->e1_ts) { LOGP(DLINP, LOGL_ERROR, "BTS %u OML link without timeslot?\n", bts->nr); return -EINVAL; } sign_ts = &line->ts[e1_link->e1_ts-1]; e1inp_ts_config_sign(sign_ts, line); oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, bts->c0, bts->oml_tei, SAPI_OML); if (!oml_link) { LOGP(DLINP, LOGL_ERROR, "BTS %u OML link creation failed\n", bts->nr); return -ENOMEM; } if (bts->oml_link) e1inp_sign_link_destroy(bts->oml_link); bts->oml_link = oml_link; rc = clock_gettime(CLOCK_MONOTONIC, &tp); bts->uptime = (rc < 0) ? 0 : tp.tv_sec; /* we don't need sub-second precision for uptime */ llist_for_each_entry(trx, &bts->trx_list, list) e1_reconfig_trx(trx); /* notify E1 input something has changed */ return e1inp_line_update(line); }
int e1_reconfig_trx(struct gsm_bts_trx *trx) { struct gsm_e1_subslot *e1_link = &trx->rsl_e1_link; struct e1inp_ts *sign_ts; struct e1inp_line *line; struct e1inp_sign_link *rsl_link; int i; if (!e1_link->e1_ts) { LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link without " "timeslot?\n", trx->bts->nr, trx->nr); return -EINVAL; } /* RSL Link */ line = e1inp_line_find(e1_link->e1_nr); if (!line) { LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link referring " "to non-existing E1 line %u\n", trx->bts->nr, trx->nr, e1_link->e1_nr); return -ENOMEM; } sign_ts = &line->ts[e1_link->e1_ts-1]; e1inp_ts_config_sign(sign_ts, line); /* Ericsson RBS have a per-TRX OML link in parallel to RSL */ if (trx->bts->type == GSM_BTS_TYPE_RBS2000) { struct e1inp_sign_link *oml_link; oml_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_OML, trx, trx->rsl_tei, SAPI_OML); if (!oml_link) { LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) OML link creation " "failed\n", trx->bts->nr, trx->nr); return -ENOMEM; } if (trx->oml_link) e1inp_sign_link_destroy(trx->oml_link); trx->oml_link = oml_link; } rsl_link = e1inp_sign_link_create(sign_ts, E1INP_SIGN_RSL, trx, trx->rsl_tei, SAPI_RSL); if (!rsl_link) { LOGP(DLINP, LOGL_ERROR, "TRX (%u/%u) RSL link creation " "failed\n", trx->bts->nr, trx->nr); return -ENOMEM; } if (trx->rsl_link) e1inp_sign_link_destroy(trx->rsl_link); trx->rsl_link = rsl_link; for (i = 0; i < TRX_NR_TS; i++) e1_reconfig_ts(&trx->ts[i]); return 0; }
/* callback of the OML listening filedescriptor */ static int listen_fd_cb(struct osmo_fd *listen_bfd, unsigned int what) { int ret; int idx = 0; int i; struct e1inp_line *line; struct e1inp_ts *e1i_ts; struct osmo_fd *bfd; struct sockaddr_in sa; socklen_t sa_len = sizeof(sa); if (!(what & BSC_FD_READ)) return 0; ret = accept(listen_bfd->fd, (struct sockaddr *) &sa, &sa_len); if (ret < 0) { perror("accept"); return ret; } LOGP(DLINP, LOGL_NOTICE, "accept()ed new HSL link from %s\n", inet_ntoa(sa.sin_addr)); /* clone virtual E1 line for this new signalling link. */ line = e1inp_line_clone(tall_hsl_ctx, listen_bfd->data); if (line == NULL) { LOGP(DLINP, LOGL_ERROR, "could not clone E1 line\n"); return -1; } /* create virrtual E1 timeslots for signalling */ e1inp_ts_config_sign(&line->ts[1-1], line); /* initialize the fds */ for (i = 0; i < ARRAY_SIZE(line->ts); ++i) line->ts[i].driver.ipaccess.fd.fd = -1; e1i_ts = &line->ts[idx]; bfd = &e1i_ts->driver.ipaccess.fd; bfd->fd = ret; bfd->data = line; bfd->priv_nr = PRIV_OML; bfd->cb = hsl_fd_cb; bfd->when = BSC_FD_READ; ret = osmo_fd_register(bfd); if (ret < 0) { LOGP(DLINP, LOGL_ERROR, "could not register FD\n"); close(bfd->fd); e1inp_line_put(line); return ret; } return ret; }