|
|
|
/* pcu_l1_if.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/core/select.h>
|
|
|
|
#include <osmocom/core/msgb.h>
|
|
|
|
#include <osmocom/core/gsmtap_util.h>
|
|
|
|
#include <osmocom/core/gsmtap.h>
|
|
|
|
#include <osmocom/core/bitvec.h>
|
|
|
|
#include <osmocom/core/sockaddr_str.h>
|
|
|
|
#include <osmocom/core/logging.h>
|
|
|
|
#include <osmocom/core/utils.h>
|
|
|
|
#include <osmocom/gprs/gprs_ns2.h>
|
|
|
|
#include <osmocom/gsm/l1sap.h>
|
|
|
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
|
|
|
#include <osmocom/gsm/gsm48_rest_octets.h>
|
|
|
|
#include <osmocom/gsm/sysinfo.h>
|
Support Neighbor Address Resolution over PCUIF IPA multiplex
While NACC was initially developed, it became clear there was need for
a way to interact PCU<->BSC in order resolve ARFCN+BSIC into CGI-PS
for later RIM usage.
Hence, this resolution was first (until today) implemented using an out
of bands RPC system using the CTRL interface, which required specific
config to be written and matches in osmo-pcu and osmo-bsc VTY (ip+port
of the CTRL interface to use).
However, this has several shortcomings:
* As explained above, specific configuration is required
* Since recently, we do support BSC redundancy in osmo-bts. Hence the BTS
may switch to a BSC other than first one. If that happened, that'd mean
the CTRL interface would still point to the initially configured one,
which may not be the same currently serving the PCU.
During recent development of ANR related features, a similar need for
PCU<->BSC was required, but this time it was decided to extend the IPA
multiplex of the Abis OML connection to pass PCUIF messages,
transparently forwarded to each side by the BTS.
This has the advantage that connection PCU<->BTS is handled by BTS and
both sides send messages transparently.
Let's switch by default to using this new interface, while still
maintaing the old way for a while (announcing them as deprecated) to
avoid breaking existing deployments until they are upgraded to new
versions of osmo-pcu and osmo-bsc.
Related: SYS#4971
Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
1 year ago
|
|
|
|
|
|
|
#include <nacc_fsm.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <gprs_rlcmac.h>
|
|
|
|
#include <pcu_l1_if.h>
|
|
|
|
#include <gprs_debug.h>
|
|
|
|
#include <gprs_bssgp_pcu.h>
|
|
|
|
#include <osmocom/pcu/pcuif_proto.h>
|
|
|
|
#include <bts.h>
|
|
|
|
#include <pdch.h>
|
|
|
|
#include <tbf_ul.h>
|
|
|
|
#include <tbf_dl.h>
|
|
|
|
#include <gprs_ms_storage.h>
|
|
|
|
|
|
|
|
// FIXME: move this, when changed from c++ to c.
|
|
|
|
extern "C" {
|
|
|
|
void *l1if_open_pdch(uint8_t trx_no, uint32_t hlayer1,
|
|
|
|
struct gsmtap_inst *gsmtap);
|
|
|
|
int l1if_connect_pdch(void *obj, uint8_t ts);
|
|
|
|
int l1if_pdch_req(void *obj, uint8_t ts, int is_ptcch, uint32_t fn,
|
|
|
|
uint16_t arfcn, uint8_t block_nr, uint8_t *data, uint8_t len);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern void *tall_pcu_ctx;
|
|
|
|
|
|
|
|
#define PAGING_GROUP_LEN 3
|
|
|
|
|
|
|
|
/* returns [0,999] on success, > 999 on error */
|
|
|
|
uint16_t imsi2paging_group(const char* imsi)
|
|
|
|
{
|
|
|
|
uint16_t pgroup = 0;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
len = (imsi != NULL) ? strlen(imsi) : 0;
|
|
|
|
if (len < PAGING_GROUP_LEN)
|
|
|
|
return 0xFFFF;
|
|
|
|
imsi += len - PAGING_GROUP_LEN;
|
|
|
|
|
|
|
|
while (*imsi != '\0') {
|
|
|
|
if (!isdigit(*imsi))
|
|
|
|
return 0xFFFF;
|
|
|
|
pgroup *= 10;
|
|
|
|
pgroup += *imsi - '0';
|
|
|
|
imsi++;
|
|
|
|
}
|
|
|
|
return pgroup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* PCU messages
|
|
|
|
*/
|
|
|
|
|
Support Neighbor Address Resolution over PCUIF IPA multiplex
While NACC was initially developed, it became clear there was need for
a way to interact PCU<->BSC in order resolve ARFCN+BSIC into CGI-PS
for later RIM usage.
Hence, this resolution was first (until today) implemented using an out
of bands RPC system using the CTRL interface, which required specific
config to be written and matches in osmo-pcu and osmo-bsc VTY (ip+port
of the CTRL interface to use).
However, this has several shortcomings:
* As explained above, specific configuration is required
* Since recently, we do support BSC redundancy in osmo-bts. Hence the BTS
may switch to a BSC other than first one. If that happened, that'd mean
the CTRL interface would still point to the initially configured one,
which may not be the same currently serving the PCU.
During recent development of ANR related features, a similar need for
PCU<->BSC was required, but this time it was decided to extend the IPA
multiplex of the Abis OML connection to pass PCUIF messages,
transparently forwarded to each side by the BTS.
This has the advantage that connection PCU<->BTS is handled by BTS and
both sides send messages transparently.
Let's switch by default to using this new interface, while still
maintaing the old way for a while (announcing them as deprecated) to
avoid breaking existing deployments until they are upgraded to new
versions of osmo-pcu and osmo-bsc.
Related: SYS#4971
Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
1 year ago
|
|
|
/* Can be used to allocate message with non-variable size */
|
|
|
|
struct msgb *pcu_msgb_alloc(uint8_t msg_type, uint8_t bts_nr)
|
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
|
|
|
|
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;
|
|
|
|
pcu_prim->bts_nr = bts_nr;
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
Support Neighbor Address Resolution over PCUIF IPA multiplex
While NACC was initially developed, it became clear there was need for
a way to interact PCU<->BSC in order resolve ARFCN+BSIC into CGI-PS
for later RIM usage.
Hence, this resolution was first (until today) implemented using an out
of bands RPC system using the CTRL interface, which required specific
config to be written and matches in osmo-pcu and osmo-bsc VTY (ip+port
of the CTRL interface to use).
However, this has several shortcomings:
* As explained above, specific configuration is required
* Since recently, we do support BSC redundancy in osmo-bts. Hence the BTS
may switch to a BSC other than first one. If that happened, that'd mean
the CTRL interface would still point to the initially configured one,
which may not be the same currently serving the PCU.
During recent development of ANR related features, a similar need for
PCU<->BSC was required, but this time it was decided to extend the IPA
multiplex of the Abis OML connection to pass PCUIF messages,
transparently forwarded to each side by the BTS.
This has the advantage that connection PCU<->BTS is handled by BTS and
both sides send messages transparently.
Let's switch by default to using this new interface, while still
maintaing the old way for a while (announcing them as deprecated) to
avoid breaking existing deployments until they are upgraded to new
versions of osmo-pcu and osmo-bsc.
Related: SYS#4971
Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
1 year ago
|
|
|
/* Allocate message with extra size, only reserve pcuif msg hdr */
|
|
|
|
static struct msgb *pcu_msgb_alloc_ext_size(uint8_t msg_type, uint8_t bts_nr, size_t extra_size)
|
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
msg = msgb_alloc(sizeof(struct gsm_pcu_if) + extra_size, "pcu_sock_tx");
|
|
|
|
/* Only header is filled, caller is responible for reserving + filling
|
|
|
|
* message type specific contents: */
|
|
|
|
msgb_put(msg, PCUIF_HDR_SIZE);
|
|
|
|
pcu_prim = (struct gsm_pcu_if *) msgb_data(msg);
|
|
|
|
pcu_prim->msg_type = msg_type;
|
|
|
|
pcu_prim->bts_nr = bts_nr;
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
const struct value_string gsm_pcu_if_text_type_names[] = {
|
|
|
|
OSMO_VALUE_STRING(PCU_VERSION),
|
|
|
|
OSMO_VALUE_STRING(PCU_OML_ALERT),
|
|
|
|
{ 0, NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
int pcu_tx_txt_ind(enum gsm_pcu_if_text_type t, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
struct gsm_pcu_if_txt_ind *txt;
|
|
|
|
va_list ap;
|
|
|
|
char *rep;
|
|
|
|
struct msgb *msg = pcu_msgb_alloc(PCU_IF_MSG_TXT_IND, 0);
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
|
|
|
txt = &pcu_prim->u.txt_ind;
|
|
|
|
txt->type = t;
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
rep = talloc_vasprintf(tall_pcu_ctx, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
if (!rep)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
osmo_strlcpy(txt->text, rep, TXT_MAX_LEN);
|
|
|
|
talloc_free(rep);
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_INFO, "Sending %s TXT as %s to BTS\n", txt->text,
|
|
|
|
get_value_string(gsm_pcu_if_text_type_names, t));
|
|
|
|
|
|
|
|
return pcu_sock_send(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_tx_act_req(struct gprs_rlcmac_bts *bts, const struct gprs_rlcmac_pdch *pdch,
|
|
|
|
uint8_t activate)
|
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
struct gsm_pcu_if_act_req *act_req;
|
|
|
|
|
|
|
|
LOGPDCH(pdch, DL1IF, LOGL_INFO, "Sending %s request\n",
|
|
|
|
(activate) ? "activate" : "deactivate");
|
|
|
|
|
|
|
|
msg = pcu_msgb_alloc(PCU_IF_MSG_ACT_REQ, bts->nr);
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
|
|
|
act_req = &pcu_prim->u.act_req;
|
|
|
|
act_req->activate = activate;
|
|
|
|
act_req->trx_nr = pdch->trx_no();
|
|
|
|
act_req->ts_nr = pdch->ts_no;
|
|
|
|
|
|
|
|
return pcu_sock_send(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_tx_data_req(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts, uint8_t sapi,
|
|
|
|
uint16_t arfcn, uint32_t fn, uint8_t block_nr, uint8_t *data,
|
|
|
|
uint8_t len)
|
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
struct gsm_pcu_if_data *data_req;
|
|
|
|
int current_fn = bts_current_frame_number(bts);
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_DEBUG, "(bts=%u,trx=%u,ts=%u) FN=%u Sending data request: sapi=%d "
|
|
|
|
"arfcn=%d cur_fn=%d block=%d data=%s\n", bts->nr, trx, ts, fn, sapi,
|
|
|
|
arfcn, current_fn, block_nr, osmo_hexdump(data, len));
|
|
|
|
|
|
|
|
msg = pcu_msgb_alloc(PCU_IF_MSG_DATA_REQ, bts->nr);
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
pcu_prim = (struct gsm_pcu_if *) msg->data;
|
|
|
|
data_req = &pcu_prim->u.data_req;
|
|
|
|
|
|
|
|
data_req->sapi = sapi;
|
|
|
|
data_req->fn = fn;
|
|
|
|
data_req->arfcn = arfcn;
|
|
|
|
data_req->trx_nr = trx;
|
|
|
|
data_req->ts_nr = ts;
|
|
|
|
data_req->block_nr = block_nr;
|
|
|
|
memcpy(data_req->data, data, len);
|
|
|
|
data_req->len = len;
|
|
|
|
|
|
|
|
return pcu_sock_send(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pcu_l1if_tx_pdtch(msgb *msg, struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts, uint16_t arfcn,
|
|
|
|
uint32_t fn, uint8_t block_nr)
|
|
|
|
{
|
|
|
|
#ifdef ENABLE_DIRECT_PHY
|
|
|
|
if (bts->trx[trx].fl1h) {
|
|
|
|
l1if_pdch_req(bts->trx[trx].fl1h, ts, 0, fn, arfcn, block_nr,
|
|
|
|
msg->data, msg->len);
|
|
|
|
msgb_free(msg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PDTCH, arfcn, fn, block_nr,
|
|
|
|
msg->data, msg->len);
|
|
|
|
msgb_free(msg);
|
|
|
|
}
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts,
|
|
|
|
uint8_t trx, uint8_t ts, uint16_t arfcn,
|
|
|
|
uint32_t fn, uint8_t block_nr,
|
|
|
|
uint8_t *data, size_t data_len)
|
|
|
|
{
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PTCCH))
|
|
|
|
gsmtap_send(the_pcu->gsmtap, arfcn, ts, GSMTAP_CHANNEL_PTCCH, 0, fn, 0, 0, data, data_len);
|
|
|
|
#ifdef ENABLE_DIRECT_PHY
|
|
|
|
if (bts->trx[trx].fl1h) {
|
|
|
|
l1if_pdch_req(bts->trx[trx].fl1h, ts, 1, fn, arfcn, block_nr, data, data_len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
pcu_tx_data_req(bts, trx, ts, PCU_IF_SAPI_PTCCH, arfcn, fn, block_nr, data, data_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pcu_l1if_tx_agch(struct gprs_rlcmac_bts *bts, bitvec * block, int plen)
|
|
|
|
{
|
|
|
|
uint8_t data[GSM_MACBLOCK_LEN]; /* prefix PLEN */
|
|
|
|
|
|
|
|
/* FIXME: why does OpenBTS has no PLEN and no fill in message? */
|
|
|
|
bitvec_pack(block, data + 1);
|
|
|
|
data[0] = (plen << 2) | 0x01;
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_AGCH))
|
|
|
|
gsmtap_send(the_pcu->gsmtap, 0, 0, GSMTAP_CHANNEL_AGCH, 0, 0, 0, 0, data, GSM_MACBLOCK_LEN);
|
|
|
|
|
|
|
|
pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, GSM_MACBLOCK_LEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec * block, int plen, uint16_t pgroup)
|
|
|
|
{
|
|
|
|
uint8_t data[PAGING_GROUP_LEN + GSM_MACBLOCK_LEN];
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* prepend paging group */
|
|
|
|
for (i = 0; i < PAGING_GROUP_LEN; i++) {
|
|
|
|
data[PAGING_GROUP_LEN - 1 - i] = '0' + (char)(pgroup % 10);
|
|
|
|
pgroup = pgroup / 10;
|
|
|
|
}
|
|
|
|
OSMO_ASSERT(pgroup == 0);
|
|
|
|
|
|
|
|
/* block provided by upper layer comes without first byte (plen),
|
|
|
|
* prepend it manually:
|
|
|
|
*/
|
|
|
|
OSMO_ASSERT(sizeof(data) >= PAGING_GROUP_LEN + 1 + block->data_len);
|
|
|
|
data[3] = (plen << 2) | 0x01;
|
|
|
|
bitvec_pack(block, data + PAGING_GROUP_LEN + 1);
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
if (the_pcu->gsmtap_categ_mask & (1 << PCU_GSMTAP_C_DL_PCH))
|
|
|
|
gsmtap_send(the_pcu->gsmtap, 0, 0, GSMTAP_CHANNEL_PCH, 0, 0, 0, 0, data + 3, GSM_MACBLOCK_LEN);
|
|
|
|
|
|
|
|
pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_PCH, 0, 0, 0, data, PAGING_GROUP_LEN + GSM_MACBLOCK_LEN);
|
|
|
|
}
|
|
|
|
|
Support Neighbor Address Resolution over PCUIF IPA multiplex
While NACC was initially developed, it became clear there was need for
a way to interact PCU<->BSC in order resolve ARFCN+BSIC into CGI-PS
for later RIM usage.
Hence, this resolution was first (until today) implemented using an out
of bands RPC system using the CTRL interface, which required specific
config to be written and matches in osmo-pcu and osmo-bsc VTY (ip+port
of the CTRL interface to use).
However, this has several shortcomings:
* As explained above, specific configuration is required
* Since recently, we do support BSC redundancy in osmo-bts. Hence the BTS
may switch to a BSC other than first one. If that happened, that'd mean
the CTRL interface would still point to the initially configured one,
which may not be the same currently serving the PCU.
During recent development of ANR related features, a similar need for
PCU<->BSC was required, but this time it was decided to extend the IPA
multiplex of the Abis OML connection to pass PCUIF messages,
transparently forwarded to each side by the BTS.
This has the advantage that connection PCU<->BTS is handled by BTS and
both sides send messages transparently.
Let's switch by default to using this new interface, while still
maintaing the old way for a while (announcing them as deprecated) to
avoid breaking existing deployments until they are upgraded to new
versions of osmo-pcu and osmo-bsc.
Related: SYS#4971
Change-Id: I6ad33c7ab10202840cf804dea9ba595978d0e920
1 year ago
|
|
|
int pcu_tx_neigh_addr_res_req(struct gprs_rlcmac_bts *bts, const struct neigh_cache_entry_key *neigh_key)
|
|
|
|
{
|
|
|
|
struct msgb *msg;
|
|
|
|
struct gsm_pcu_if *pcu_prim;
|
|
|
|
struct gsm_pcu_if_neigh_addr_req *naddr_req;
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_DEBUG, "(bts=%u) Tx Neighbor Address Resolution Request: " NEIGH_CACHE_ENTRY_KEY_FMT "\n",
|
|
|
|
bts->nr, NEIGH_CACHE_ENTRY_KEY_ARGS(neigh_key));
|
|
|
|
|
|
|
|
msg = pcu_msgb_alloc_ext_size(PCU_IF_MSG_CONTAINER, bts->nr, sizeof(struct gsm_pcu_if_neigh_addr_req));
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
pcu_prim = (struct gsm_pcu_if *) msgb_data(msg);
|
|
|
|
naddr_req = (struct gsm_pcu_if_neigh_addr_req *)&pcu_prim->u.container.data[0];
|
|
|
|
|
|
|
|
msgb_put(msg, sizeof(pcu_prim->u.container) + sizeof(struct gsm_pcu_if_neigh_addr_req));
|
|
|
|
pcu_prim->u.container.msg_type = PCU_IF_MSG_NEIGH_ADDR_REQ;
|
|
|
|
osmo_store16be(sizeof(struct gsm_pcu_if_neigh_addr_req), &pcu_prim->u.container.length);
|
|
|
|
|
|
|
|
osmo_store16be(neigh_key->local_lac, &naddr_req->local_lac);
|
|
|
|
osmo_store16be(neigh_key->local_ci, &naddr_req->local_ci);
|
|
|
|
osmo_store16be(neigh_key->tgt_arfcn, &naddr_req->tgt_arfcn);
|
|
|
|
naddr_req->tgt_bsic = neigh_key->tgt_bsic;
|
|
|
|
|
|
|
|
return pcu_sock_send(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pcu_rx_block_time(struct gprs_rlcmac_bts *bts, uint16_t arfcn, uint32_t fn, uint8_t ts_no)
|
|
|
|
{
|
|
|
|
bts_set_current_block_frame_number(bts, fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
int pcu_rx_data_ind_pdtch(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_pdch *pdch, uint8_t *data,
|
|
|
|
uint8_t len, uint32_t fn, struct pcu_l1_meas *meas)
|
|
|
|
{
|
Add new PDCH UL Controller, drop SBAllocator class
Right now we handle different types of UL allocations in different
classes like PollAllocator and SBAllocator, and they usually don't take
into account the other one in most cases. Furthermore, those objects are
usually per-BTS object, instead of per PDCH object.
This is a first step towards having a unified per-PDCH controller which
takes care of controlling what is scheduled and hence expected on the
uplink. Each PDCH has a UL Controller which keeps track of all reserved
uplink frame, be it SB, RRBP poll or USF assigned, all under the same
API.
As a first step, only the SBA part is fully implemented and used (being
it the easiest part to replace); TBF poll+usf will come in follow-up
patches later on. As a result, the SBAllocator per-BTS class dissappears
but some of its code is refactored/reused to provide more features to the
gprs_rlcmac_sba object, which is also further integrated into the new UL
Controller.
Related: OS#5020
Change-Id: I84b24beea4a1aa2c1528f41435f77bd16df2b947
2 years ago
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (!pdch->is_enabled()) {
|
|
|
|
LOGPDCH(pdch, DL1IF, LOGL_INFO, "Received DATA.ind (PDTCH) on disabled TS\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
Add new PDCH UL Controller, drop SBAllocator class
Right now we handle different types of UL allocations in different
classes like PollAllocator and SBAllocator, and they usually don't take
into account the other one in most cases. Furthermore, those objects are
usually per-BTS object, instead of per PDCH object.
This is a first step towards having a unified per-PDCH controller which
takes care of controlling what is scheduled and hence expected on the
uplink. Each PDCH has a UL Controller which keeps track of all reserved
uplink frame, be it SB, RRBP poll or USF assigned, all under the same
API.
As a first step, only the SBA part is fully implemented and used (being
it the easiest part to replace); TBF poll+usf will come in follow-up
patches later on. As a result, the SBAllocator per-BTS class dissappears
but some of its code is refactored/reused to provide more features to the
gprs_rlcmac_sba object, which is also further integrated into the new UL
Controller.
Related: OS#5020
Change-Id: I84b24beea4a1aa2c1528f41435f77bd16df2b947
2 years ago
|
|
|
rc = pdch->rcv_block(data, len, fn, meas);
|
|
|
|
pdch_ulc_expire_fn(pdch->ulc, fn);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int list_arfcn(const struct gprs_rlcmac_bts *bts, const struct gsm_sysinfo_freq *freq, const char *text)
|
|
|
|
{
|
|
|
|
int n = 0, i;
|
|
|
|
for (i = 0; i < 1024; i++) {
|
|
|
|
if (freq[i].mask) {
|
|
|
|
if (!n)
|
|
|
|
LOGP(DL1IF, LOGL_INFO, "BTS%d: %s", bts->nr, text);
|
|
|
|
LOGPC(DL1IF, LOGL_INFO, " %d", i);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (n)
|
|
|
|
LOGPC(DL1IF, LOGL_INFO, "\n");
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_rx_data_ind_bcch(struct gprs_rlcmac_bts *bts, uint8_t *data, uint8_t len)
|
|
|
|
{
|
|
|
|
struct gsm48_system_information_type_2 *si2;
|
|
|
|
const uint8_t *si_ro;
|
|
|
|
|
|
|
|
switch (len) {
|
|
|
|
case 0:
|
|
|
|
/* Due to historical reasons also accept a completely empty message as
|
|
|
|
* revoke command for SI13. */
|
|
|
|
LOGP(DL1IF, LOGL_ERROR,
|
|
|
|
"Received PCU data indication that contains no data -- Revoked SI13.\n");
|
|
|
|
bts->si13_is_set = false;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
case 1:
|
|
|
|
/* Revoke SI, type is identified by a single byte which is coded after
|
|
|
|
* enum osmo_sysinfo_type. */
|
|
|
|
switch (data[0]) {
|
|
|
|
case SYSINFO_TYPE_1:
|
|
|
|
bts->si1_is_set = false;
|
|
|
|
break;
|
|
|
|
case SYSINFO_TYPE_2:
|
|
|
|
bts->si2_is_set = false;
|
|
|
|
break;
|
|
|
|
case SYSINFO_TYPE_3:
|
|
|
|
bts->si3_is_set = false;
|
|
|
|
break;
|
|
|
|
case SYSINFO_TYPE_13:
|
|
|
|
bts->si13_is_set = false;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR,
|
|
|
|
"Received PCU data indication that contains an unsupported system information identifier (%02x,OSMO) -- ignored.\n", data[0]);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
LOGP(DPCU, LOGL_DEBUG,
|
|
|
|
"Received PCU data indication: Revoked SI%s\n",
|
|
|
|
get_value_string(osmo_sitype_strs, data[0]));
|
|
|
|
return 0;
|
|
|
|
case GSM_MACBLOCK_LEN:
|
|
|
|
/* Update SI, type is identified by the RR sysinfo type, which is the
|
|
|
|
* 3rd byte in the buffer. */
|
|
|
|
switch (data[2]) {
|
|
|
|
case GSM48_MT_RR_SYSINFO_1:
|
|
|
|
memcpy(bts->si1, data, GSM_MACBLOCK_LEN);
|
|
|
|
bts->si1_is_set = true;
|
|
|
|
break;
|
|
|
|
case GSM48_MT_RR_SYSINFO_2:
|
|
|
|
memcpy(bts->si2, data, GSM_MACBLOCK_LEN);
|
|
|
|
bts->si2_is_set = true;
|
|
|
|
si2 = (struct gsm48_system_information_type_2 *)bts->si2;
|
|
|
|
gsm48_decode_freq_list(bts->si2_bcch_cell_list, si2->bcch_frequency_list,
|
|
|
|
sizeof(si2->bcch_frequency_list), 0xce, 1);
|
|
|
|
list_arfcn(bts, bts->si2_bcch_cell_list, "SI2 Neighbour cells in same band:");
|
|
|
|
break;
|
|
|
|
case GSM48_MT_RR_SYSINFO_3:
|
|
|
|
memcpy(bts->si3, data, GSM_MACBLOCK_LEN);
|
|
|
|
bts->si3_is_set = true;
|
|
|
|
break;
|
|
|
|
case GSM48_MT_RR_SYSINFO_13:
|
|
|
|
memcpy(bts->si13, data, GSM_MACBLOCK_LEN);
|
|
|
|
bts->si13_is_set = true;
|
|
|
|
si_ro = ((struct gsm48_system_information_type_13*)data)->rest_octets;
|
|
|
|
if (osmo_gsm48_rest_octets_si13_decode(&bts->si13_ro_decoded, si_ro) < 0)
|
|
|
|
LOGP(DPCU, LOGL_ERROR, "Error decoding SI13\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR,
|
|
|
|
"Received PCU data indication that contains an unsupported system information identifier (%02x,RR) -- ignored.\n", data[2]);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
LOGP(DPCU, LOGL_DEBUG,
|
|
|
|
"Received PCU data indication: Updated %s: %s\n",
|
|
|
|
gsm48_pdisc_msgtype_name(data[1], data[2]),
|
|
|
|
osmo_hexdump_nospc(data + 1, GSM_MACBLOCK_LEN));
|
|
|
|
return 0;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR,
|
|
|
|
"Received PCU data indication with unexpected data length: %u -- ignored.\n",
|
|
|
|
len);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_rx_data_ind(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data *data_ind)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
int current_fn = bts_current_frame_number(bts);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2 years ago
|
|
|
struct pcu_l1_meas meas = {0};
|
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
uint8_t gsmtap_chantype;
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_DEBUG, "(bts=%" PRIu8 ",trx=%" PRIu8 ",ts=%" PRIu8 ") FN=%u "
|
|
|
|
"Rx DATA.ind: sapi=%d arfcn=%d cur_fn=%d "
|
|
|
|
"block=%d data=%s\n", bts->nr, data_ind->trx_nr, data_ind->ts_nr,
|
|
|
|
data_ind->fn, data_ind->sapi, data_ind->arfcn, current_fn,
|
|
|
|
data_ind->block_nr, osmo_hexdump(data_ind->data, data_ind->len));
|
|
|
|
|
|
|
|
switch (data_ind->sapi) {
|
|
|
|
case PCU_IF_SAPI_PDTCH:
|
|
|
|
pdch = &bts->trx[data_ind->trx_nr].pdch[data_ind->ts_nr];
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2 years ago
|
|
|
pcu_l1_meas_set_rssi(&meas, data_ind->rssi);
|
|
|
|
/* convert BER to % value */
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2 years ago
|
|
|
pcu_l1_meas_set_ber(&meas, data_ind->ber10k / 100);
|
|
|
|
pcu_l1_meas_set_bto(&meas, data_ind->ta_offs_qbits);
|
|
|
|
pcu_l1_meas_set_link_qual(&meas, data_ind->lqual_cb / 10);
|
|
|
|
|
|
|
|
LOGPDCH(pdch, DL1IF, LOGL_DEBUG, "FN=%u Rx DATA.ind PDTCH: "
|
|
|
|
"BER10k = %d, BTO = %d, Q = %d\n", data_ind->fn,
|
|
|
|
data_ind->ber10k, data_ind->ta_offs_qbits, data_ind->lqual_cb);
|
|
|
|
|
|
|
|
rc = pcu_rx_data_ind_pdtch(bts, pdch, data_ind->data, data_ind->len,
|
|
|
|
data_ind->fn, &meas);
|
|
|
|
gsmtap_chantype = GSMTAP_CHANNEL_PDTCH;
|
|
|
|
break;
|
|
|
|
case PCU_IF_SAPI_BCCH:
|
|
|
|
rc = pcu_rx_data_ind_bcch(bts, data_ind->data, data_ind->len);
|
|
|
|
gsmtap_chantype = GSMTAP_CHANNEL_BCCH;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR, "(bts=%" PRIu8 ",trx=%" PRIu8 ",ts=%" PRIu8 ") "
|
|
|
|
"FN=%u Rx DATA.ind with unsupported sapi %d\n",
|
|
|
|
bts->nr, data_ind->trx_nr, data_ind->ts_nr, data_ind->fn, data_ind->sapi);
|
|
|
|
rc = -EINVAL;
|
|
|
|
gsmtap_chantype = GSMTAP_CHANNEL_UNKNOWN;
|
|
|
|
}
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
if (rc < 0 && (the_pcu->gsmtap_categ_mask & (1 <<PCU_GSMTAP_C_UL_UNKNOWN))) {
|
|
|
|
gsmtap_send(the_pcu->gsmtap, data_ind->arfcn | GSMTAP_ARFCN_F_UPLINK, data_ind->ts_nr,
|
|
|
|
gsmtap_chantype, 0, data_ind->fn, meas.rssi, meas.link_qual, data_ind->data, data_ind->len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_rx_data_cnf(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data *data_cnf)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
int current_fn = bts_current_frame_number(bts);
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_DEBUG, "Data confirm received: sapi=%d fn=%d cur_fn=%d\n",
|
|
|
|
data_cnf->sapi, data_cnf->fn, current_fn);
|
|
|
|
|
|
|
|
switch (data_cnf->sapi) {
|
|
|
|
case PCU_IF_SAPI_PCH:
|
|
|
|
if (data_cnf->data[2] == 0x3f)
|
|
|
|
bts_rcv_imm_ass_cnf(bts, data_cnf->data, data_cnf->fn);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR, "Received PCU data confirm with "
|
|
|
|
"unsupported sapi %d\n", data_cnf->sapi);
|
|
|
|
rc = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: remove this, when changed from c++ to c.
|
|
|
|
int pcu_rx_rts_req_pdtch(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts,
|
|
|
|
uint32_t fn, uint8_t block_nr)
|
|
|
|
{
|
|
|
|
return gprs_rlcmac_rcv_rts_block(bts,
|
|
|
|
trx, ts, fn, block_nr);
|
|
|
|
}
|
|
|
|
int pcu_rx_rts_req_ptcch(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts,
|
|
|
|
uint32_t fn, uint8_t block_nr)
|
|
|
|
{
|
|
|
|
struct gprs_rlcmac_pdch *pdch;
|
|
|
|
|
|
|
|
/* Prevent buffer overflow */
|
|
|
|
if (trx >= ARRAY_SIZE(bts->trx) || ts >= 8)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Make sure PDCH time-slot is enabled */
|
|
|
|
pdch = &bts->trx[trx].pdch[ts];
|
|
|
|
if (!pdch->m_is_enabled)
|
|
|
|
return -EAGAIN;
|
|
|
|
|
Split PCU global PCU object from BTS object
Currently the BTS object (and gprs_rlcmac_bts struct) are used to hold
both PCU global fields and BTS specific fields, all mangled together.
The BTS is even accessed in lots of places by means of a singleton.
This patch introduces a new struct gprs_pcu object aimed at holding all
global state, and several fields are already moved from BTS to it. The
new object can be accessed as global variable "the_pcu", reusing and
including an already exisitng "the_pcu" global variable only used for
bssgp related purposes so far.
This is only a first step towards having a complete split global pcu and
BTS, some fields are still kept in BTS and will be moved over follow-up
smaller patches in the future (since this patch is already quite big).
So far, the code still only supports one BTS, which can be accessed
using the_pcu->bts. In the future that field will be replaced with a
list, and the BTS singletons will be removed.
The cur_fn output changes in TbfTest are actually a side effect fix,
since the singleton main_bts() now points internally to the_pcu->bts,
hence the same we allocate and assign in the test. Beforehand, "the_bts"
was allocated in the stack while main_bts() still returned an unrelated
singleton BTS object instance.
Related: OS#4935
Change-Id: I88e3c6471b80245ce3798223f1a61190f14aa840
2 years ago
|
|
|
pcu_l1if_tx_ptcch(bts, trx, ts, bts->trx[trx].arfcn, fn, block_nr,
|
|
|
|
pdch->ptcch_msg, GSM_MACBLOCK_LEN);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_rx_rts_req(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_rts_req *rts_req)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
int current_fn = bts_current_frame_number(bts);
|
|
|
|
const struct gprs_rlcmac_pdch *pdch;
|
|
|
|
pdch = &bts->trx[rts_req->trx_nr].pdch[rts_req->ts_nr];
|
|
|
|
|
|
|
|
LOGPDCH(pdch, DL1IF, LOGL_DEBUG, "FN=%u RX RTS.req: sapi=%d "
|
|
|
|
"arfcn=%d cur_fn=%d block=%d\n", rts_req->fn,
|
|
|
|
rts_req->sapi, rts_req->arfcn, current_fn, rts_req->block_nr);
|
|
|
|
|
|
|
|
switch (rts_req->sapi) {
|
|
|
|
case PCU_IF_SAPI_PDTCH:
|
|
|
|
pcu_rx_rts_req_pdtch(bts, rts_req->trx_nr, rts_req->ts_nr,
|
|
|
|
rts_req->fn, rts_req->block_nr);
|
|
|
|
break;
|
|
|
|
case PCU_IF_SAPI_PTCCH:
|
|
|
|
pcu_rx_rts_req_ptcch(bts, rts_req->trx_nr, rts_req->ts_nr,
|
|
|
|
rts_req->fn, rts_req->block_nr);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOGP(DL1IF, LOGL_ERROR, "(bts=%u,trx=%u,ts=%u) FN=%u RX RTS.req with "
|
|
|
|
"unsupported sapi %d\n", bts->nr, rts_req->trx_nr, rts_req->ts_nr,
|
|
|
|
rts_req->fn, rts_req->sapi);
|
|
|
|
rc = -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* C -> C++ adapter for direct DSP access code (e.g. osmo-bts-sysmo) */
|
|
|
|
extern "C" int pcu_rx_rach_ind_ptcch(struct gprs_rlcmac_bts *bts, uint8_t trx_nr, uint8_t ts_nr, uint32_t fn, int16_t qta)
|
|
|
|
{
|
|
|
|
struct rach_ind_params rip = {
|
|
|
|
/* The content of RA is not of interest on PTCCH/U */
|
|
|
|
.burst_type = GSM_L1_BURST_TYPE_ACCESS_0,
|
|
|
|
.is_11bit = false,
|
|
|
|
.ra = 0x00,
|
|
|
|
.trx_nr = trx_nr,
|
|
|
|
.ts_nr = ts_nr,
|
|
|
|
.rfn = fn,
|
|
|
|
.qta = qta,
|
|
|
|
};
|
|
|
|
|
|
|
|
return bts_rcv_ptcch_rach(bts, &rip);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pcu_rx_rach_ind(struct gprs_rlcmac_bts *bts, const struct gsm_pcu_if_rach_ind *rach_ind)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
int current_fn = bts_current_frame_number(bts);
|
|
|
|
|
|
|
|
LOGP(DL1IF, LOGL_INFO, "RACH request received: sapi=%d "
|
|
|
|
"qta=%d, ra=0x%02x, fn=%u, cur_fn=%d, is_11bit=%d\n", rach_ind->sapi, rach_ind->qta,
|
|