aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/pcu/pcuif_proto.h13
-rw-r--r--src/bts.cpp35
-rw-r--r--src/pcu_l1_if.cpp24
-rw-r--r--src/pcu_l1_if.h1
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..0950f7a7 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, false, GSM_RESERVED_TMSI);
+ 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, false, GSM_RESERVED_TMSI);
+ 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..4af6953f 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 confirm flag is set, the receiving end is required to send a confirmation
+ * back 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