From d8ed63af17e9356fc64cfca84412160b9e8a8033 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Fri, 25 Aug 2023 12:58:32 +0200 Subject: [PATCH] pcu_l1_if: add support for PCU_IF_SAPI_AGCH_2 for PCUIF v.11 When an downlink IMMEDIATE ASSIGNMENT message is sent through the PCH, an IMSI is always required in order to be able to calculate the paging group. However, when the downlink IMMEDIATE ASSIGNMENT has to be sent before the MS has completed the GMM ATTACH REQUEST, the IMSI is still unknown. In this case we may assume that the MS is still in non-DRX mode, which means it listens on all CCCH blocks (PCH and AGCH). This means we may send the IMMEDIATE ASSIGNMENT through the AGCH in this situation. This will also have the advantage that the scheduling through the AGCH will have less latency than the paging queue. Unfortunately the SAPI PCU_IF_SAPI_AGCH only supports sending whole MAC blocks, so it won't be possible to attach a TLLI that can be used for confirmation. To fix this, let's add a new SAPI_PCUI_IF_AGCH_2, that works similar as SAPI PCU_IF_SAPI_PCH_2 and use it to send the IMMEDIATE ASSIGNMENT through the AGCH. CAUTION: This patch breaks compatibility with current master osmo-bts and osmo-bsc (see "Depends") Related: OS#5927 Depends: osmo-bts.git I29858fa20ad8bd0aefe81a5c40ad77a2559a8c10 Change-Id: I9effdcec1da91a6e2e7a7c41f95d3300ad1bb292 --- include/osmocom/pcu/pcuif_proto.h | 13 ++++++++++++ src/bts.cpp | 35 +++++++++++++++++++++++++------ src/pcu_l1_if.cpp | 24 +++++++++++++++++++++ src/pcu_l1_if.h | 1 + 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/include/osmocom/pcu/pcuif_proto.h b/include/osmocom/pcu/pcuif_proto.h index aa22447e..cd2a2983 100644 --- a/include/osmocom/pcu/pcuif_proto.h +++ b/include/osmocom/pcu/pcuif_proto.h @@ -42,6 +42,7 @@ #define PCU_IF_SAPI_PRACH 0x06 /* packet random access channel */ #define PCU_IF_SAPI_PTCCH 0x07 /* packet TA control channel */ #define PCU_IF_SAPI_PCH_2 0x08 /* assignment on PCH (confirmed using message id) */ +#define PCU_IF_SAPI_AGCH_2 0x09 /* assignment on AGCH (confirmed using message id) */ /* flags */ #define PCU_IF_FLAG_ACTIVE (1 << 0)/* BTS is active */ @@ -276,6 +277,18 @@ struct gsm_pcu_if_pch { bool confirm; } __attribute__((packed)); +/* Struct to send a (confirmed) IMMEDIATE ASSIGNMENT message via AGCH. The struct is sent as a data request + * (data_req) under SAPI PCU_IF_SAPI_AGCH_2. */ +struct gsm_pcu_if_agch { + /* message id as reference for confirmation */ + uint32_t msg_id; + /* GSM mac-block (with immediate assignment message) */ + uint8_t data[GSM_MACBLOCK_LEN]; + /* Set to true in case the receiving end must send a confirmation + * when the MAC block (data) has been sent. */ + bool confirm; +} __attribute__((packed)); + struct gsm_pcu_if { /* context based information */ uint8_t msg_type; /* message type */ diff --git a/src/bts.cpp b/src/bts.cpp index 5c483d5c..c86c3dc5 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -1033,7 +1033,10 @@ int bts_rcv_rach(struct gprs_rlcmac_bts *bts, const struct rach_ind_params *rip) rip->burst_type); bts_do_rate_ctr_inc(bts, CTR_IMMEDIATE_ASSIGN_UL_TBF); if (plen >= 0) { - pcu_l1if_tx_agch(bts, bv, plen); + if (the_pcu->pcu_if_version >= 0x0b) + pcu_l1if_tx_agch2(bts, bv, plen, GSM_RESERVED_TMSI, false); + else + pcu_l1if_tx_agch(bts, bv, plen); rc = 0; } else { rc = plen; @@ -1047,8 +1050,12 @@ send_imm_ass_rej: bv, rip->ra, rip->rfn, rip->burst_type, (uint8_t)osmo_tdef_get(bts->T_defs_bts, 3142, OSMO_TDEF_S, -1)); bts_do_rate_ctr_inc(bts, CTR_IMMEDIATE_ASSIGN_REJ); - if (plen >= 0) - pcu_l1if_tx_agch(bts, bv, plen); + if (plen >= 0) { + if (the_pcu->pcu_if_version >= 0x0b) + pcu_l1if_tx_agch2(bts, bv, plen, GSM_RESERVED_TMSI, false); + else + pcu_l1if_tx_agch(bts, bv, plen); + } bitvec_free(bv); /* rc was already properly set before goto */ return rc; @@ -1128,10 +1135,26 @@ void bts_snd_dl_ass(struct gprs_rlcmac_bts *bts, const struct gprs_rlcmac_dl_tbf GSM_L1_BURST_TYPE_ACCESS_0); if (plen >= 0) { bts_do_rate_ctr_inc(bts, CTR_IMMEDIATE_ASSIGN_DL_TBF); - if (the_pcu->pcu_if_version >= 0x0b) - pcu_l1if_tx_pch2(bts, immediate_assignment, plen, true, tbf->imsi(), tbf->tlli()); - else + + if (the_pcu->pcu_if_version >= 0x0b) { + if (ms_imsi_is_valid(tbf->ms())) { + pcu_l1if_tx_pch2(bts, immediate_assignment, plen, true, tbf->imsi(), tbf->tlli()); + } else { + /* During GMM ATTACH REQUEST, the IMSI is not yet known to the PCU or SGSN. (It is requested + * after the GMM ATTACH REQUEST with the GMM IDENTITY REQUEST.) When the PCU has to assign a + * DL TBF but the IMSI is not known, then the IMMEDIATE ASSIGNMENT is sent on the AGCH. The + * reason for this is that without an IMSI we can not calculate the paging group, which would + * be necessary for transmission on PCH. Since the IMSI is usually only unknown during the GMM + * ATTACH REQUEST, we may assume that the MS is in non-DRX mode and hence it is listening on + * all CCCH blocks, including AGCH. + * + * See also: 3gpp TS 44.060, section 5.5.1.5 + * 3gpp TS 45.002, section 6.5.3, 6.5.6 */ + pcu_l1if_tx_agch2(bts, immediate_assignment, plen, true, tbf->tlli()); + } + } else { pcu_l1if_tx_pch(bts, immediate_assignment, plen, tbf->imsi()); + } } bitvec_free(immediate_assignment); diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index f92f08ea..7bc4cb9c 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -251,6 +251,8 @@ void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts, void pcu_l1if_tx_agch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen) { + /* TODO: When PCUIF v.11 has become mainline, we will use pcu_l1if_tx_agch2() exclusively. + * This will make this function obsolote, so we can remove it. */ uint8_t data[GSM_MACBLOCK_LEN]; /* prefix PLEN */ /* FIXME: why does OpenBTS has no PLEN and no fill in message? */ @@ -263,10 +265,31 @@ void pcu_l1if_tx_agch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen) pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, sizeof(data)); } +/* Send a MAC block via the access grant channel. This will (obviously) only work for MAC blocks that contain + * an IMMEDIATE ASSIGNMENT. In case the MAC block contains an IMMEDIATE ASSIGNMENT message, the receiving end + * is required to confirm when the IMMEDIATE ASSIGNMENT has been sent. */ +void pcu_l1if_tx_agch2(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, bool confirm, uint32_t msg_id) +{ + struct gsm_pcu_if_agch agch = { 0 }; + + agch.confirm = confirm; + agch.msg_id = msg_id; + agch.data[0] = (plen << 2) | 0x01; + bitvec_pack(block, agch.data + 1); + + 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, agch.data, GSM_MACBLOCK_LEN); + + pcu_tx_data_req(bts, 0, 0, PCU_IF_SAPI_AGCH_2, 0, 0, 0, (uint8_t*)&agch, sizeof(agch)); +} + #define IMSI_DIGITS_FOR_PAGING 3 /* Send a MAC block via the paging channel. (See also comment below) */ void pcu_l1if_tx_pch(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, const char *imsi) { + /* TODO: When PCUIF v.11 has become mainline, we will use pcu_l1if_tx_pch2() exclusively. + * This will make this function obsolote, so we can remove it. */ + uint8_t data[IMSI_DIGITS_FOR_PAGING + GSM_MACBLOCK_LEN]; /* prepend last three IMSI digits (if present) from which BTS/BSC will calculate the paging group */ @@ -561,6 +584,7 @@ static int pcu_rx_data_cnf2(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_data_ switch (data_cnf->sapi) { case PCU_IF_SAPI_PCH_2: + case PCU_IF_SAPI_AGCH_2: bts_rcv_imm_ass_cnf(bts, NULL, data_cnf->msg_id); break; default: diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index 138636d3..b6da337b 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -147,6 +147,7 @@ void pcu_l1if_tx_ptcch(struct gprs_rlcmac_bts *bts, uint32_t fn, uint8_t block_nr, uint8_t *data, size_t data_len); void pcu_l1if_tx_agch(struct gprs_rlcmac_bts *bts, bitvec *block, int len); +void pcu_l1if_tx_agch2(struct gprs_rlcmac_bts *bts, bitvec *block, int plen, bool confirm, uint32_t msg_id); #endif #ifdef __cplusplus