aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2023-05-31 12:20:55 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2023-07-21 13:20:06 +0200
commit6fa1dfce614da9f9cca642e68402fe5cbaf175d3 (patch)
tree33fbccd422aa8740bdf5c70e92157e623b46dae4 /src
parent65c8f0de946fb61b059bee45abae1372430ddf8b (diff)
ASCI: Add Notification CHannel (NCH) support
The location of the NCH is defined by the rest octet of System Information 1. If NCH is defined, the given CCCH blocks are used for NCH instead of AGCH/PCH. The current list of VGCS/VBS call notifications is transmitted on the NCH. If there is no notification, an empty notification is transmitted on the NCH. The Notification List Number (NLN) is used to indicated new notificaitons. Only the last notification (or empty notification) indicates NLN. This way the MS can determine after two equal NLN that the complete list has been recevied. Change-Id: I82fdaba3faaced76267a99ae14a5458a1b41fdaa Related: OS#5781
Diffstat (limited to 'src')
-rw-r--r--src/common/bts.c34
-rw-r--r--src/common/l1sap.c27
-rw-r--r--src/common/notification.c70
3 files changed, 112 insertions, 19 deletions
diff --git a/src/common/bts.c b/src/common/bts.c
index b4a5f804..7257f37b 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -56,6 +56,7 @@
#include <osmo-bts/nm_common_fsm.h>
#include <osmo-bts/power_control.h>
#include <osmo-bts/osmux.h>
+#include <osmo-bts/notification.h>
#define MIN_QUAL_RACH 50 /* minimum link quality (in centiBels) for Access Bursts */
#define MIN_QUAL_NORM -5 /* minimum link quality (in centiBels) for Normal Bursts */
@@ -723,8 +724,7 @@ static void compact_agch_queue(struct gsm_bts *bts)
return;
}
-int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt,
- int is_ag_res)
+int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt, enum ccch_msgt ccch)
{
struct msgb *msg = NULL;
int rc = 0;
@@ -737,17 +737,25 @@ int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt
*/
compact_agch_queue(bts);
- /* Check for paging messages first if this is PCH */
- if (!is_ag_res)
- rc = paging_gen_msg(bts->paging_state, out_buf, gt, &is_empty);
-
- /* Check whether the block may be overwritten */
- if (!is_empty)
- return rc;
-
- msg = bts_agch_dequeue(bts);
- if (!msg)
+ switch (ccch) {
+ case CCCH_MSGT_NCH:
+ /* Send NCH message, it has priority over AGCH and does not overlap with PCH. */
+ rc = bts_asci_notify_nch_gen_msg(bts, out_buf);
return rc;
+ case CCCH_MSGT_PCH:
+ /* Check whether the block may be overwritten by AGCH. */
+ rc = paging_gen_msg(bts->paging_state, out_buf, gt, &is_empty);
+ if (!is_empty)
+ return rc;
+ /* fall-through */
+ case CCCH_MSGT_AGCH:
+ /* If fallen here and the AGCH queue is empty, return empty PCH message. */
+ msg = bts_agch_dequeue(bts);
+ if (!msg)
+ return rc;
+ /* Continue to return AGCH message. */
+ break;
+ }
rate_ctr_inc2(bts->ctrs, BTS_CTR_AGCH_SENT);
@@ -756,7 +764,7 @@ int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt
rc = msgb_l3len(msg);
msgb_free(msg);
- if (is_ag_res)
+ if (ccch == CCCH_MSGT_AGCH)
bts->agch_queue.agch_msgs++;
else
bts->agch_queue.pch_msgs++;
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index 1c43f8ff..268486e0 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -902,15 +902,32 @@ static int lchan_pdtch_ph_rts_ind_loop(struct gsm_lchan *lchan,
return 0;
}
-/* Check if given CCCH frame number is for a PCH or for an AGCH (this function is
+/* Check if given CCCH frame number is for a NCH, PCH or for an AGCH (this function is
* only used internally, it is public to call it from unit-tests) */
-int is_ccch_for_agch(struct gsm_bts_trx *trx, uint32_t fn) {
+enum ccch_msgt get_ccch_msgt(struct gsm_bts_trx *trx, uint32_t fn)
+{
+ uint8_t block, first_block, num_blocks;
+ int rc;
+
+ block = l1sap_fn2ccch_block(fn);
+
+ /* If there is an NCH, check if the block number matches. It has priority over PCH/AGCH. */
+ if (trx->bts->asci.pos_nch >= 0) {
+ rc = osmo_gsm48_si1ro_nch_pos_decode(trx->bts->asci.pos_nch, &num_blocks, &first_block);
+ if (rc >= 0 && block >= first_block && block < first_block + num_blocks)
+ return CCCH_MSGT_NCH;
+ }
+
/* Note: The number of available access grant channels is set by the
* parameter BS_AG_BLKS_RES via system information type 3. This SI is
* transferred to osmo-bts via RSL */
- return l1sap_fn2ccch_block(fn) < num_agch(trx, "PH-RTS-IND");
+ if (l1sap_fn2ccch_block(fn) < num_agch(trx, "PH-RTS-IND"))
+ return CCCH_MSGT_AGCH;
+
+ return CCCH_MSGT_PCH;
}
+
/* return the measured average of frame numbers that the RTS clock is running in advance */
int32_t bts_get_avg_fn_advance(const struct gsm_bts *bts)
{
@@ -1048,7 +1065,6 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
struct msgb *pp_msg;
bool dtxd_facch = false;
int rc;
- int is_ag_res;
chan_nr = rts_ind->chan_nr;
link_id = rts_ind->link_id;
@@ -1183,8 +1199,7 @@ static int l1sap_ph_rts_ind(struct gsm_bts_trx *trx,
}
} else if (L1SAP_IS_CHAN_AGCH_PCH(chan_nr)) {
p = msgb_put(msg, GSM_MACBLOCK_LEN);
- is_ag_res = is_ccch_for_agch(trx, fn);
- rc = bts_ccch_copy_msg(trx->bts, p, &g_time, is_ag_res);
+ rc = bts_ccch_copy_msg(trx->bts, p, &g_time, get_ccch_msgt(trx, fn));
if (rc <= 0)
memcpy(p, fill_frame, GSM_MACBLOCK_LEN);
}
diff --git a/src/common/notification.c b/src/common/notification.c
index 1fda5194..35dc65f9 100644
--- a/src/common/notification.c
+++ b/src/common/notification.c
@@ -71,6 +71,10 @@ int bts_asci_notification_add(struct gsm_bts *bts, const uint8_t *group_call_ref
/* add at beginning of "queue" to make sure a new call is notified first */
llist_add(&n->list, &bts->asci.notifications);
+ bts->asci.notification_entries++;
+ bts->asci.notification_count = 0;
+ bts->asci.nln = (bts->asci.nln + 1) % 4;
+
return 0;
}
@@ -86,6 +90,10 @@ int bts_asci_notification_del(struct gsm_bts *bts, const uint8_t *group_call_ref
llist_del(&n->list);
talloc_free(n);
+ bts->asci.notification_entries--;
+ bts->asci.notification_count = 0;
+ bts->asci.nln_status = (bts->asci.nln_status + 1) % 2;
+
return 0;
}
@@ -100,6 +108,11 @@ int bts_asci_notification_reset(struct gsm_bts *bts)
llist_del(&n->list);
talloc_free(n);
}
+
+ bts->asci.notification_entries = 0;
+ bts->asci.notification_count = 0;
+ bts->asci.nln_status = (bts->asci.nln_status + 1) % 2;
+
return 0;
}
@@ -153,3 +166,60 @@ void append_group_call_information(struct bitvec *bv, const uint8_t *gcr, const
bitvec_free(gcr_bv);
}
+
+#define L2_PLEN(len) (((len - 1) << 2) | 0x01)
+
+int bts_asci_notify_nch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf)
+{
+ struct gsm48_notification_nch *nn = (struct gsm48_notification_nch *) out_buf;
+ const struct asci_notification *notif;
+ unsigned int ro_len;
+
+ notif = bts_asci_notification_get_next(bts);
+
+ *nn = (struct gsm48_notification_nch) {
+ .proto_discr = GSM48_PDISC_RR,
+ .msg_type = GSM48_MT_RR_NOTIF_NCH,
+ };
+
+ nn->l2_plen = L2_PLEN(nn->data - out_buf);
+
+ /* Pad remaining octets with constant '2B'O */
+ ro_len = GSM_MACBLOCK_LEN - (nn->data - out_buf);
+ memset(nn->data, GSM_MACBLOCK_PADDING, ro_len);
+
+ struct bitvec bv = {
+ .data_len = ro_len,
+ .data = nn->data,
+ };
+
+ /* {0 | 1 < NLN(NCH) : bit (2) >}
+ * Only send NLN, at the last notifications.
+ * When the phone receives two NLN with the same value, it knows that all notifications has been received.
+ * Also send NLN if no notification is available. */
+ if (bts->asci.notification_count >= bts->asci.notification_entries - 1) {
+ bitvec_set_bit(&bv, 1);
+ bitvec_set_uint(&bv, bts->asci.nln, 2);
+ } else {
+ bitvec_set_bit(&bv, 0);
+ }
+
+ /* Count NLN. */
+ if (++bts->asci.notification_count >= bts->asci.notification_entries)
+ bts->asci.notification_count = 0;
+
+ /* < List of Group Call NCH information > ::=
+ * { 0 | 1 < Group Call information > < List of Group Call NCH information > } ; */
+ if (notif) {
+ bitvec_set_bit(&bv, 1);
+ append_group_call_information(&bv, notif->group_call_ref,
+ notif->chan_desc.present ? notif->chan_desc.value : NULL,
+ notif->chan_desc.len);
+ }
+ bitvec_set_bit(&bv, 0); /* End of list */
+
+ /* TODO: Additions in Release 6 */
+ /* TODO: Additions in Release 7 */
+
+ return GSM_MACBLOCK_LEN;
+}