diff options
Diffstat (limited to 'openbsc/src/libbsc/pcu_sock.c')
-rw-r--r-- | openbsc/src/libbsc/pcu_sock.c | 214 |
1 files changed, 69 insertions, 145 deletions
diff --git a/openbsc/src/libbsc/pcu_sock.c b/openbsc/src/libbsc/pcu_sock.c index 62f18a783..ccc0e9a01 100644 --- a/openbsc/src/libbsc/pcu_sock.c +++ b/openbsc/src/libbsc/pcu_sock.c @@ -33,20 +33,18 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/select.h> #include <osmocom/core/socket.h> -#include <osmo-bts/logging.h> -#include <osmo-bts/gsm_data.h> -#include <osmo-bts/pcu_if.h> -#include <osmo-bts/pcuif_proto.h> -#include <osmo-bts/bts.h> -#include <osmo-bts/rsl.h> -#include <osmo-bts/signal.h> -#include <osmo-bts/l1sap.h> +#include <osmocom/core/logging.h> +#include <osmocom/gsm/l1sap.h> -uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx); +#include <openbsc/gsm_data.h> +#include <openbsc/pcu_if.h> +#include <openbsc/pcuif_proto.h> +#include <openbsc/signal.h> +#include <openbsc/debug.h> -extern struct gsm_network bts_gsmnet; +static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg); +uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx); int pcu_direct = 0; -static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0}; static const char *sapi_string[] = { [PCU_IF_SAPI_RACH] = "RACH", @@ -58,9 +56,6 @@ static const char *sapi_string[] = { [PCU_IF_SAPI_PTCCH] = "PTCCH", }; -static int pcu_sock_send(struct gsm_network *net, struct msgb *msg); - - static struct gsm_bts_trx *trx_by_nr(struct gsm_bts *bts, uint8_t trx_nr) { struct gsm_bts_trx *trx; @@ -73,11 +68,11 @@ static struct gsm_bts_trx *trx_by_nr(struct gsm_bts *bts, uint8_t trx_nr) return NULL; } - /* * PCU messages */ +/* Set up an message buffer to package an pcu interface message */ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr) { struct msgb *msg; @@ -86,6 +81,7 @@ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr) msg = msgb_alloc(sizeof(struct gsm_pcu_if), "pcu_sock_tx"); if (!msg) return NULL; + msgb_put(msg, sizeof(struct gsm_pcu_if)); pcu_prim = (struct gsm_pcu_if *) msg->data; pcu_prim->msg_type = msg_type; @@ -94,6 +90,7 @@ struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr) return msg; } +/* Helper function exclusivly used by pcu_if_signal_cb() */ static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) { if (ts->pchan == GSM_PCHAN_PDCH) return true; @@ -120,44 +117,42 @@ static bool ts_should_be_pdch(struct gsm_bts_trx_ts *ts) { return false; } -int pcu_tx_info_ind(void) +/* Send BTS properties to the PCU */ +static int pcu_tx_info_ind(struct gsm_bts *bts) { - struct gsm_network *net = &bts_gsmnet; struct msgb *msg; struct gsm_pcu_if *pcu_prim; struct gsm_pcu_if_info_ind *info_ind; - struct gsm_bts *bts; struct gprs_rlc_cfg *rlcc; struct gsm_bts_gprs_nsvc *nsvc; struct gsm_bts_trx *trx; struct gsm_bts_trx_ts *ts; int i, j; - LOGP(DPCU, LOGL_INFO, "Sending info\n"); + printf("======================= PCU UPDATE! =========================\n"); + + OSMO_ASSERT(bts); + OSMO_ASSERT(bts->network); + + LOGP(DPCU, LOGL_INFO, "Sending info for BTS %d\n",bts->nr); - /* FIXME: allow multiple BTS */ - bts = llist_entry(net->bts_list.next, struct gsm_bts, list); rlcc = &bts->gprs.cell.rlc_cfg; msg = pcu_msgb_alloc(PCU_IF_MSG_INFO_IND, bts->nr); if (!msg) return -ENOMEM; + pcu_prim = (struct gsm_pcu_if *) msg->data; info_ind = &pcu_prim->u.info_ind; info_ind->version = PCU_IF_VERSION; - - if (avail_lai && avail_nse && avail_cell && avail_nsvc[0]) { - info_ind->flags |= PCU_IF_FLAG_ACTIVE; - LOGP(DPCU, LOGL_INFO, "BTS is up\n"); - } else - LOGP(DPCU, LOGL_INFO, "BTS is down\n"); + info_ind->flags |= PCU_IF_FLAG_ACTIVE; if (pcu_direct) info_ind->flags |= PCU_IF_FLAG_SYSMO; /* RAI */ - info_ind->mcc = net->mcc; - info_ind->mnc = net->mnc; + info_ind->mcc = bts->network->country_code; + info_ind->mnc = bts->network->network_code; info_ind->lac = bts->location_area_code; info_ind->rac = bts->gprs.rac; @@ -228,7 +223,6 @@ int pcu_tx_info_ind(void) break; info_ind->trx[i].pdch_mask = 0; info_ind->trx[i].arfcn = trx->arfcn; - info_ind->trx[i].hlayer1 = trx_get_hlayer1(trx); for (j = 0; j < 8; j++) { ts = &trx->ts[j]; if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED @@ -245,76 +239,22 @@ int pcu_tx_info_ind(void) } } - return pcu_sock_send(net, msg); + return pcu_sock_send(bts, msg); } -static int pcu_if_signal_cb(unsigned int subsys, unsigned int signal, - void *hdlr_data, void *signal_data) +void pcu_info_update(struct gsm_bts *bts) { - struct gsm_network *net = &bts_gsmnet; - struct gsm_bts_gprs_nsvc *nsvc; - struct gsm_bts *bts; - struct gsm48_system_information_type_3 *si3; - int id; - - if (subsys != SS_GLOBAL) - return -EINVAL; - - switch(signal) { - case S_NEW_SYSINFO: - bts = signal_data; - if (!(bts->si_valid & (1 << SYSINFO_TYPE_3))) - break; - si3 = (struct gsm48_system_information_type_3 *) - bts->si_buf[SYSINFO_TYPE_3]; - net->mcc = ((si3->lai.digits[0] & 0x0f) << 8) - | (si3->lai.digits[0] & 0xf0) - | (si3->lai.digits[1] & 0x0f); - net->mnc = ((si3->lai.digits[2] & 0x0f) << 8) - | (si3->lai.digits[2] & 0xf0) - | ((si3->lai.digits[1] & 0xf0) >> 4); - if ((net->mnc & 0x00f) == 0x00f) - net->mnc >>= 4; - bts->location_area_code = ntohs(si3->lai.lac); - bts->cell_identity = si3->cell_identity; - avail_lai = 1; - break; - case S_NEW_NSE_ATTR: - bts = signal_data; - avail_nse = 1; - break; - case S_NEW_CELL_ATTR: - bts = signal_data; - avail_cell = 1; - break; - case S_NEW_NSVC_ATTR: - nsvc = signal_data; - id = nsvc->id; - if (id < 0 || id > 1) - return -EINVAL; - avail_nsvc[id] = 1; - break; - case S_NEW_OP_STATE: - break; - default: - return -EINVAL; - } - - /* If all infos have been received, of if one info is updated after - * all infos have been received, transmit info update. */ - if (avail_lai && avail_nse && avail_cell && avail_nsvc[0]) - pcu_tx_info_ind(); - return 0; + if (pcu_connected(bts)) + pcu_tx_info_ind(bts); } -int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, +int pcu_tx_rts_req(struct gsm_bts *bts, struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, uint16_t arfcn, uint8_t block_nr) { struct msgb *msg; struct gsm_pcu_if *pcu_prim; struct gsm_pcu_if_rts_req *rts_req; - struct gsm_bts *bts = ts->trx->bts; LOGP(DPCU, LOGL_DEBUG, "Sending rts request: is_ptcch=%d arfcn=%d " "block=%d\n", is_ptcch, arfcn, block_nr); @@ -332,17 +272,16 @@ int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, rts_req->ts_nr = ts->nr; rts_req->block_nr = block_nr; - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } -int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, +int pcu_tx_data_ind(struct gsm_bts *bts, struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len, int8_t rssi, uint16_t ber10k, int16_t bto, int16_t lqual) { struct msgb *msg; struct gsm_pcu_if *pcu_prim; struct gsm_pcu_if_data *data_ind; - struct gsm_bts *bts = ts->trx->bts; LOGP(DPCU, LOGL_DEBUG, "Sending data indication: is_ptcch=%d arfcn=%d " "block=%d data=%s\n", is_ptcch, arfcn, block_nr, @@ -368,9 +307,10 @@ int pcu_tx_data_ind(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn, memcpy(data_ind->data, data, len); data_ind->len = len; - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } +/* Forward rach indication to PCU */ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit, enum ph_burst_type burst_type) { @@ -394,10 +334,10 @@ int pcu_tx_rach_ind(struct gsm_bts *bts, int16_t qta, uint16_t ra, uint32_t fn, rach_ind->is_11bit = is_11bit; rach_ind->burst_type = burst_type; - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } -int pcu_tx_time_ind(uint32_t fn) +int pcu_tx_time_ind(struct gsm_bts *bts, uint32_t fn) { struct msgb *msg; struct gsm_pcu_if *pcu_prim; @@ -416,12 +356,14 @@ int pcu_tx_time_ind(uint32_t fn) time_ind->fn = fn; - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } -int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed) +/* Forward paging information to PCU */ +int pcu_tx_pag_req(struct gsm_bts *bts, const uint8_t *identity_lv, + uint8_t chan_needed) { - struct pcu_sock_state *state = bts_gsmnet.pcu_state; + struct pcu_sock_state *state = bts->pcu_state; struct msgb *msg; struct gsm_pcu_if *pcu_prim; struct gsm_pcu_if_pag_req *pag_req; @@ -449,20 +391,15 @@ int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed) pag_req->chan_needed = chan_needed; memcpy(pag_req->identity_lv, identity_lv, identity_lv[0] + 1); - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } -int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len) +int pcu_tx_pch_data_cnf(struct gsm_bts *bts, uint32_t fn, uint8_t *data, uint8_t len) { - struct gsm_network *net = &bts_gsmnet; - struct gsm_bts *bts; struct msgb *msg; struct gsm_pcu_if *pcu_prim; struct gsm_pcu_if_data *data_cnf; - /* FIXME: allow multiple BTS */ - bts = llist_entry(net->bts_list.next, struct gsm_bts, list); - LOGP(DPCU, LOGL_INFO, "Sending PCH confirm\n"); msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_CNF, bts->nr); @@ -476,7 +413,7 @@ int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len) memcpy(data_cnf->data, data, len); data_cnf->len = len; - return pcu_sock_send(&bts_gsmnet, msg); + return pcu_sock_send(bts, msg); } static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, @@ -502,7 +439,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, } else { bts->si_valid &= ~(1 << SYSINFO_TYPE_13); } - osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts); + // osmo_signal_dispatch(SS_GLOBAL, S_NEW_SYSINFO, bts); break; case PCU_IF_SAPI_PCH: if (msg_type == PCU_IF_MSG_PAG_REQ) { @@ -512,8 +449,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, } else { struct gsm_bts_role_bts *btsb = bts->role; - paging_add_imm_ass(btsb->paging_state, data_req->data, - data_req->len); + printf("paging_add_imm_ass(btsb->paging_state, data_req->data,data_req->len);\n"); } break; case PCU_IF_SAPI_AGCH: @@ -524,7 +460,8 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, } msg->l3h = msgb_put(msg, data_req->len); memcpy(msg->l3h, data_req->data, data_req->len); - if (bts_agch_enqueue(bts, msg) < 0) { + + if (rsl_imm_assign_cmd(bts, msg->len, msg->data)) { msgb_free(msg); rc = -EIO; } @@ -540,8 +477,8 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, } ts = &trx->ts[data_req->ts_nr]; is_ptcch = (data_req->sapi == PCU_IF_SAPI_PTCCH); - rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn, - data_req->block_nr, data_req->data, data_req->len); + printf("rc = l1sap_pdch_req(ts, is_ptcch, data_req->fn, data_req->arfcn,data_req->block_nr, data_req->data, data_req->len);\n"); + rc = -EINVAL; break; default: LOGP(DPCU, LOGL_ERROR, "Received PCU data request with " @@ -552,8 +489,7 @@ static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type, return rc; } -static int pcu_rx_act_req(struct gsm_bts *bts, - struct gsm_pcu_if_act_req *act_req) +static int pcu_rx_act_req(struct gsm_bts *bts, struct gsm_pcu_if_act_req *act_req) { struct gsm_bts_trx *trx; struct gsm_lchan *lchan; @@ -567,7 +503,7 @@ static int pcu_rx_act_req(struct gsm_bts *bts, return -EINVAL; lchan = trx->ts[act_req->ts_nr].lchan; - lchan->rel_act_kind = LCHAN_REL_ACT_PCU; +// lchan->rel_act_kind = LCHAN_REL_ACT_PCU; if (lchan->type != GSM_LCHAN_PDTCH) { LOGP(DPCU, LOGL_ERROR, "%s request, but lchan is not of type PDTCH (is %s)\n", @@ -576,9 +512,9 @@ static int pcu_rx_act_req(struct gsm_bts *bts, return -EINVAL; } if (act_req->activate) - l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan), NULL); + printf("l1sap_chan_act(trx, gsm_lchan2chan_nr(lchan), NULL);\n"); else - l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan)); + printf("l1sap_chan_rel(trx, gsm_lchan2chan_nr(lchan));\n"); return 0; } @@ -613,16 +549,9 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type, * PCU socket interface */ -struct pcu_sock_state { - struct gsm_network *net; - struct osmo_fd listen_bfd; /* fd for listen socket */ - struct osmo_fd conn_bfd; /* fd for connection to lcr */ - struct llist_head upqueue; /* queue for sending messages */ -}; - -static int pcu_sock_send(struct gsm_network *net, struct msgb *msg) +static int pcu_sock_send(struct gsm_bts *bts, struct msgb *msg) { - struct pcu_sock_state *state = net->pcu_state; + struct pcu_sock_state *state = bts->pcu_state; struct osmo_fd *conn_bfd; struct gsm_pcu_if *pcu_prim = (struct gsm_pcu_if *) msg->data; @@ -682,9 +611,8 @@ static void pcu_sock_close(struct pcu_sock_state *state) ts = &trx->ts[j]; if (ts->mo.nm_state.operational == NM_OPSTATE_ENABLED && ts->pchan == GSM_PCHAN_PDCH) { - ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU; - l1sap_chan_rel(trx, - gsm_lchan2chan_nr(ts->lchan)); +// ts->lchan->rel_act_kind = LCHAN_REL_ACT_PCU; + printf("l1sap_chan_rel(trx,gsm_lchan2chan_nr(ts->lchan));\n"); } } } @@ -836,13 +764,11 @@ static int pcu_sock_accept(struct osmo_fd *bfd, unsigned int flags) LOGP(DPCU, LOGL_NOTICE, "PCU socket connected to external PCU\n"); - /* send current info */ - pcu_tx_info_ind(); - return 0; } -int pcu_sock_init(const char *path) +/* Open connection to PCU */ +int pcu_sock_init(const char *path, struct gsm_bts *bts) { struct pcu_sock_state *state; struct osmo_fd *bfd; @@ -853,7 +779,7 @@ int pcu_sock_init(const char *path) return -ENOMEM; INIT_LLIST_HEAD(&state->upqueue); - state->net = &bts_gsmnet; + state->net = bts->network; state->conn_bfd.fd = -1; bfd = &state->listen_bfd; @@ -880,22 +806,19 @@ int pcu_sock_init(const char *path) return rc; } - osmo_signal_register_handler(SS_GLOBAL, pcu_if_signal_cb, NULL); - - bts_gsmnet.pcu_state = state; - + bts->pcu_state = state; return 0; } -void pcu_sock_exit(void) +/* Close connection to PCU */ +void pcu_sock_exit(struct gsm_bts *bts) { - struct pcu_sock_state *state = bts_gsmnet.pcu_state; + struct pcu_sock_state *state = bts->pcu_state; struct osmo_fd *bfd, *conn_bfd; if (!state) return; - osmo_signal_unregister_handler(SS_GLOBAL, pcu_if_signal_cb, NULL); conn_bfd = &state->conn_bfd; if (conn_bfd->fd > 0) pcu_sock_close(state); @@ -903,12 +826,13 @@ void pcu_sock_exit(void) close(bfd->fd); osmo_fd_unregister(bfd); talloc_free(state); - bts_gsmnet.pcu_state = NULL; + bts->pcu_state = NULL; } -bool pcu_connected(void) { - struct gsm_network *net = &bts_gsmnet; - struct pcu_sock_state *state = net->pcu_state; +/* Check if BTS has a PCU connection */ +bool pcu_connected(struct gsm_bts *bts) +{ + struct pcu_sock_state *state = bts->pcu_state; if (!state) return false; |