pcu_l1_if.cpp: handle TLLI based IMMEDIATE ASSIGNMENT confirmation
The IMMEDIATE ASSIGNMENT for downlink TBFs must be confirmed by the receiving end (BSC/BTS) in order to set the timers in the PCU correctly. When the PCU is used in a BSC co-located scheme (Ericsson RBS). The TLLI is used as an identifier to confirm a specific IMMEDIATE ASSIGNMENT. Change-Id: Icf7ca34500984239ee877ee71fd9c126b5eb3480 Related: OS#5198
This commit is contained in:
parent
d8cea3c618
commit
7c3fd98c90
44
src/bts.cpp
44
src/bts.cpp
|
@ -668,13 +668,10 @@ int bts_tfi_find_free(const struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_di
|
||||||
return best_first_tfi;
|
return best_first_tfi;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bts_rcv_imm_ass_cnf(struct gprs_rlcmac_bts *bts, const uint8_t *data, uint32_t fn)
|
static int tlli_from_imm_ass(uint32_t *tlli, const uint8_t *data, uint32_t fn)
|
||||||
{
|
{
|
||||||
struct gprs_rlcmac_dl_tbf *dl_tbf;
|
|
||||||
const struct gsm48_imm_ass *imm_ass = (struct gsm48_imm_ass *)data;
|
const struct gsm48_imm_ass *imm_ass = (struct gsm48_imm_ass *)data;
|
||||||
uint8_t plen;
|
uint8_t plen;
|
||||||
uint32_t tlli;
|
|
||||||
GprsMs *ms;
|
|
||||||
|
|
||||||
/* Move to IA Rest Octets: TS 44.018 9.1.18 "The L2 pseudo length of
|
/* Move to IA Rest Octets: TS 44.018 9.1.18 "The L2 pseudo length of
|
||||||
* this message is the sum of lengths of all information elements
|
* this message is the sum of lengths of all information elements
|
||||||
|
@ -692,12 +689,41 @@ int bts_rcv_imm_ass_cnf(struct gprs_rlcmac_bts *bts, const uint8_t *data, uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get TLLI from downlink assignment */
|
/* get TLLI from downlink assignment */
|
||||||
tlli = (uint32_t)((*data++) & 0xf) << 28;
|
*tlli = (uint32_t)((*data++) & 0xf) << 28;
|
||||||
tlli |= (*data++) << 20;
|
*tlli |= (*data++) << 20;
|
||||||
tlli |= (*data++) << 12;
|
*tlli |= (*data++) << 12;
|
||||||
tlli |= (*data++) << 4;
|
*tlli |= (*data++) << 4;
|
||||||
tlli |= (*data++) >> 4;
|
*tlli |= (*data++) >> 4;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bts_rcv_imm_ass_cnf(struct gprs_rlcmac_bts *bts, const uint8_t *data, uint32_t tlli, uint32_t fn)
|
||||||
|
{
|
||||||
|
struct gprs_rlcmac_dl_tbf *dl_tbf;
|
||||||
|
GprsMs *ms;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* NOTE: A confirmation for a downlink IMMEDIATE ASSIGNMENT can be received using two different methods.
|
||||||
|
* One way is to send the whole IMMEDIATE ASSIGNMENT back to the PCU and the TLLI, which we use as
|
||||||
|
* reference is extracted from the rest octets of this message. Alternatively the TLLI may be sent as
|
||||||
|
* confirmation directly. */
|
||||||
|
|
||||||
|
/* Extract TLLI from the presented IMMEDIATE ASSIGNMENT
|
||||||
|
* (if present and only when TLLI that is supplied as function parameter is valid.) */
|
||||||
|
if (data && tlli == GSM_RESERVED_TMSI) {
|
||||||
|
rc = tlli_from_imm_ass(&tlli, data, fn);
|
||||||
|
if (rc != 0)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure TLLI is valid */
|
||||||
|
if (tlli == GSM_RESERVED_TMSI) {
|
||||||
|
LOGP(DTBFDL, LOGL_ERROR, "FN=%u Got IMM.ASS confirm, but TLLI is invalid!\n", fn);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find related TBF and send confirmation signal to FSM */
|
||||||
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
ms = bts_ms_by_tlli(bts, tlli, GSM_RESERVED_TMSI);
|
||||||
if (!ms) {
|
if (!ms) {
|
||||||
LOGP(DTBFDL, LOGL_ERROR, "FN=%u Got IMM.ASS confirm for unknown MS with TLLI=%08x\n", fn, tlli);
|
LOGP(DTBFDL, LOGL_ERROR, "FN=%u Got IMM.ASS confirm for unknown MS with TLLI=%08x\n", fn, tlli);
|
||||||
|
|
|
@ -315,7 +315,7 @@ int bts_tfi_find_free(const struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_di
|
||||||
|
|
||||||
int bts_rcv_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip);
|
int bts_rcv_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip);
|
||||||
int bts_rcv_ptcch_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip);
|
int bts_rcv_ptcch_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip);
|
||||||
int bts_rcv_imm_ass_cnf(struct gprs_rlcmac_bts *bts, const uint8_t *data, uint32_t fn);
|
int bts_rcv_imm_ass_cnf(struct gprs_rlcmac_bts *bts, const uint8_t *data, uint32_t tlli, uint32_t fn);
|
||||||
|
|
||||||
void bts_send_gsmtap(struct gprs_rlcmac_bts *bts,
|
void bts_send_gsmtap(struct gprs_rlcmac_bts *bts,
|
||||||
enum pcu_gsmtap_category categ, bool uplink, uint8_t trx_no,
|
enum pcu_gsmtap_category categ, bool uplink, uint8_t trx_no,
|
||||||
|
|
|
@ -512,7 +512,7 @@ static int pcu_rx_data_cnf(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data *
|
||||||
switch (data_cnf->sapi) {
|
switch (data_cnf->sapi) {
|
||||||
case PCU_IF_SAPI_PCH:
|
case PCU_IF_SAPI_PCH:
|
||||||
if (data_cnf->data[2] == GSM48_MT_RR_IMM_ASS)
|
if (data_cnf->data[2] == GSM48_MT_RR_IMM_ASS)
|
||||||
bts_rcv_imm_ass_cnf(bts, data_cnf->data, data_cnf->fn);
|
bts_rcv_imm_ass_cnf(bts, data_cnf->data, GSM_RESERVED_TMSI, data_cnf->fn);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOGP(DL1IF, LOGL_ERROR, "Received PCU data confirm with "
|
LOGP(DL1IF, LOGL_ERROR, "Received PCU data confirm with "
|
||||||
|
@ -523,6 +523,26 @@ static int pcu_rx_data_cnf(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data *
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pcu_rx_data_cnf_dt(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data_cnf_dt *data_cnf_dt)
|
||||||
|
{
|
||||||
|
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_dt->sapi, data_cnf_dt->fn, current_fn);
|
||||||
|
|
||||||
|
switch (data_cnf_dt->sapi) {
|
||||||
|
case PCU_IF_SAPI_PCH:
|
||||||
|
bts_rcv_imm_ass_cnf(bts, NULL, data_cnf_dt->tlli, data_cnf_dt->fn);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGP(DL1IF, LOGL_ERROR, "Received PCU data confirm with unsupported sapi %d\n", data_cnf_dt->sapi);
|
||||||
|
rc = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: remove this, when changed from c++ to c.
|
// 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,
|
int pcu_rx_rts_req_pdtch(struct gprs_rlcmac_bts *bts, uint8_t trx, uint8_t ts,
|
||||||
uint32_t fn, uint8_t block_nr)
|
uint32_t fn, uint8_t block_nr)
|
||||||
|
@ -1133,6 +1153,10 @@ int pcu_rx(struct gsm_pcu_if *pcu_prim, size_t pcu_prim_length)
|
||||||
CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.data_cnf);
|
CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.data_cnf);
|
||||||
rc = pcu_rx_data_cnf(bts, &pcu_prim->u.data_cnf);
|
rc = pcu_rx_data_cnf(bts, &pcu_prim->u.data_cnf);
|
||||||
break;
|
break;
|
||||||
|
case PCU_IF_MSG_DATA_CNF_DT:
|
||||||
|
CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.data_cnf_dt);
|
||||||
|
rc = pcu_rx_data_cnf_dt(bts, &pcu_prim->u.data_cnf_dt);
|
||||||
|
break;
|
||||||
case PCU_IF_MSG_RTS_REQ:
|
case PCU_IF_MSG_RTS_REQ:
|
||||||
CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.rts_req);
|
CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.rts_req);
|
||||||
rc = pcu_rx_rts_req(bts, &pcu_prim->u.rts_req);
|
rc = pcu_rx_rts_req(bts, &pcu_prim->u.rts_req);
|
||||||
|
|
Loading…
Reference in New Issue