pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31177 )
Change subject: rlcmac: Introduce lower primitive layer API ......................................................................
rlcmac: Introduce lower primitive layer API
This primitive API allows the application to drive the RLCMAC layer based on a lower L1CTL interface.
* RACH req are requested to the lower layers by the RLCMAC through the RACH.req primitive. * Received ImmAss, SI are fed to the RLC/MAC layer through CCCH_DATA.ind * The RLCMAC registers DL and UL TBFs in the lower part (firwmare, L1CTL): ** The lower part will trigger PDCH_RTS.ind in every TS in the "(dl_slotmask|ul_slotmask)" superset, with the received USF. This allows UL uplink to transmit blocks when requested by USF, or UL/DL TBF to answer polls from PCU at a specific N+X FN (RRBP). This also allows the RLCMAC layer to update its GSM clock and trigger internall timeouts. ** The lower part will trigger PDCH_DATA.ind in every TS in the dl_slotmask if either a CTRL block is received or a data block matching the configured dl_tfi is received. ** Upon receival of PDCH_DATA.ind, the RLCMAC layer updates its FN clock and submits PDCH_DATA.req based on USF.
This commit only adds the primitive set and API to submit/receive them, but doesn't really implement them yet internally.
Related: OS#5500 Change-Id: I3d97425ec75059ceae983de869419230e8c4df01 --- M include/osmocom/gprs/rlcmac/rlcmac_prim.h M include/osmocom/gprs/rlcmac/rlcmac_private.h M src/rlcmac/rlcmac_prim.c M tests/rlcmac/Makefile.am A tests/rlcmac/rlcmac_prim_test.c A tests/rlcmac/rlcmac_prim_test.err A tests/rlcmac/rlcmac_prim_test.ok M tests/testsuite.at 8 files changed, 477 insertions(+), 4 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/rlcmac/rlcmac_prim.h b/include/osmocom/gprs/rlcmac/rlcmac_prim.h index 443dede..92e644e 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac_prim.h +++ b/include/osmocom/gprs/rlcmac/rlcmac_prim.h @@ -15,6 +15,7 @@ enum osmo_gprs_rlcmac_prim_sap { OSMO_GPRS_RLCMAC_SAP_GRR, OSMO_GPRS_RLCMAC_SAP_GMMRR, + OSMO_GPRS_RLCMAC_SAP_L1CTL, };
extern const struct value_string osmo_gprs_rlcmac_prim_sap_names[]; @@ -87,11 +88,85 @@ }; };
+/* From/Towards lower layers */ +enum osmo_gprs_rlcmac_l1ctl_prim_type { + OSMO_GPRS_RLCMAC_L1CTL_RACH, + OSMO_GPRS_RLCMAC_L1CTL_CCCH_DATA, + OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, + OSMO_GPRS_RLCMAC_L1CTL_PDCH_RTS, + OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, + OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, +}; + +extern const struct value_string osmo_gprs_rlcmac_l1ctl_prim_type_names[]; +static inline const char *osmo_gprs_rlcmac_l1ctl_prim_type_name(enum osmo_gprs_rlcmac_l1ctl_prim_type val) +{ + return get_value_string(osmo_gprs_rlcmac_l1ctl_prim_type_names, val); +} + +/* Parameters for OSMO_GPRS_RLCMAC_L1CTL_* prims */ +struct osmo_gprs_rlcmac_l1ctl_prim { + /* Common fields (none) */ + union { + /* OSMO_GPRS_RLCMAC_L1CTL_RACH | Req */ + struct { + bool is_11bit; + union { + uint8_t ra; + struct { + uint16_t ra11; + uint8_t synch_seq; + }; + }; + } rach_req; + /* OSMO_GPRS_RLCMAC_L1CTL_CCCH_DATA | Ind */ + struct { + uint32_t fn; + uint8_t *data; /* data_len = GSM_MACBLOCK_LEN */ + } ccch_data_ind; + /* OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA | Req */ + struct { + uint32_t fn; + uint8_t ts_nr; + uint8_t data_len; + uint8_t *data; + } pdch_data_req; + /* OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA | Ind */ + struct { + uint32_t fn; + uint8_t ts_nr; + uint8_t rx_lev; + uint16_t ber10k; + int16_t ci_cb; + uint8_t data_len; /* data_len = 0 if decoding fails or filtered by lower layer based on DL TFI */ + uint8_t *data; + } pdch_data_ind; + /* OSMO_GPRS_RLCMAC_L1CTL_PDCH_RTS | Ind */ + struct { + uint32_t fn; + uint8_t ts_nr; + uint8_t usf; + } pdch_rts_ind; + /* OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF | Req */ + struct { + uint8_t ul_tbf_nr; + uint8_t ul_slotmask; + } cfg_ul_tbf_req; + /* OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF | Req */ + struct { + uint8_t dl_tbf_nr; + uint8_t dl_slotmask; + uint8_t dl_tfi; + } cfg_dl_tbf_req; + }; +}; + struct osmo_gprs_rlcmac_prim { struct osmo_prim_hdr oph; union { struct osmo_gprs_rlcmac_grr_prim grr; struct osmo_gprs_rlcmac_gmmrr_prim gmmrr; + struct osmo_gprs_rlcmac_l1ctl_prim l1ctl; }; };
@@ -113,3 +188,10 @@ /* Alloc primitive for GMMRR SAP: */ struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_gmmrr_asign_req( uint32_t new_tlli); + +/* Alloc primitive for L1CTL SAP: */ +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(uint32_t fn, uint8_t *data); +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(uint8_t ts_nr, uint32_t fn, + uint8_t rx_lev, uint16_t ber10k, int16_t ci_cb, + uint8_t *data, uint8_t data_len); +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(uint8_t ts_nr, uint32_t fn, uint8_t usf); diff --git a/include/osmocom/gprs/rlcmac/rlcmac_private.h b/include/osmocom/gprs/rlcmac/rlcmac_private.h index 26284c1..c10b159 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac_private.h +++ b/include/osmocom/gprs/rlcmac/rlcmac_private.h @@ -46,3 +46,10 @@ struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_grr_unitdata_ind( uint32_t tlli, uint8_t *ll_pdu, size_t ll_pdu_len); struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_gmmrr_page_ind(uint32_t tlli); + +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_rach8_req(uint8_t ra); +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_rach11_req(uint16_t ra11, uint8_t synch_seq); +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_pdch_data_req(uint8_t ts_nr, uint32_t fn, + uint8_t *data, uint8_t data_len); +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_cfg_dl_tbf_req(uint8_t dl_tbf_nr, uint8_t dl_slotmask, uint8_t dl_tfi); +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_cfg_ul_tbf_req(uint8_t ul_tbf_nr, uint8_t ul_slotmask); diff --git a/src/rlcmac/rlcmac_prim.c b/src/rlcmac/rlcmac_prim.c index 8d57580..a2f2576 100644 --- a/src/rlcmac/rlcmac_prim.c +++ b/src/rlcmac/rlcmac_prim.c @@ -42,6 +42,7 @@ const struct value_string osmo_gprs_rlcmac_prim_sap_names[] = { { OSMO_GPRS_RLCMAC_SAP_GRR, "GRR" }, { OSMO_GPRS_RLCMAC_SAP_GMMRR, "GMMRR" }, + { OSMO_GPRS_RLCMAC_SAP_L1CTL, "L1CTL" }, { 0, NULL } };
@@ -57,6 +58,16 @@ { 0, NULL } };
+const struct value_string osmo_gprs_rlcmac_l1ctl_prim_type_names[] = { + { OSMO_GPRS_RLCMAC_L1CTL_RACH, "RACH" }, + { OSMO_GPRS_RLCMAC_L1CTL_CCCH_DATA, "CCCH_DATA" }, + { OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, "PDCH_DATA" }, + { OSMO_GPRS_RLCMAC_L1CTL_PDCH_RTS, "PDCH_RTS" }, + { OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, "CFG_UL_TBF" }, + { OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, "CFG_DL_TBF" }, + { 0, NULL } +}; + const char *osmo_gprs_rlcmac_prim_name(const struct osmo_gprs_rlcmac_prim *rlcmac_prim) { static char name_buf[256]; @@ -71,6 +82,9 @@ case OSMO_GPRS_RLCMAC_SAP_GMMRR: type = osmo_gprs_rlcmac_gmmrr_prim_type_name(rlcmac_prim->oph.primitive); break; + case OSMO_GPRS_RLCMAC_SAP_L1CTL: + type = osmo_gprs_rlcmac_l1ctl_prim_type_name(rlcmac_prim->oph.primitive); + break; default: type = "unsupported-rlcmac-sap"; } @@ -152,6 +166,14 @@ return gprs_rlcmac_prim_alloc(OSMO_GPRS_RLCMAC_SAP_GMMRR, type, operation, l3_len); }
+static inline +struct osmo_gprs_rlcmac_prim *rlcmac_prim_l1ctl_alloc(enum osmo_gprs_rlcmac_l1ctl_prim_type type, + enum osmo_prim_operation operation, + unsigned int l3_len) +{ + return gprs_rlcmac_prim_alloc(OSMO_GPRS_RLCMAC_SAP_L1CTL, type, operation, l3_len); +} + /* 3GPP TS 44.064 7.2.3.2 GRR-UNITDATA.ind (MS):*/ struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_grr_unitdata_ind( uint32_t tlli, uint8_t *ll_pdu, @@ -195,6 +217,98 @@ return rlcmac_prim; }
+/* L1CTL-RACH.req (8bit) */ +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_rach8_req(uint8_t ra) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_RACH, PRIM_OP_REQUEST, 0); + rlcmac_prim->l1ctl.rach_req.is_11bit = false; + rlcmac_prim->l1ctl.rach_req.ra = ra; + return rlcmac_prim; +} + +/* L1CTL-RACH.req (11bit) */ +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_rach11_req(uint16_t ra11, uint8_t synch_seq) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_RACH, PRIM_OP_REQUEST, 0); + rlcmac_prim->l1ctl.rach_req.is_11bit = true; + rlcmac_prim->l1ctl.rach_req.ra11 = ra11; + rlcmac_prim->l1ctl.rach_req.synch_seq = synch_seq; + return rlcmac_prim; +} + +/* L1CTL-CCCH_DATA.ind */ +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(uint32_t fn, uint8_t *data) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_CCCH_DATA, PRIM_OP_INDICATION, 0); + rlcmac_prim->l1ctl.ccch_data_ind.fn = fn; + rlcmac_prim->l1ctl.ccch_data_ind.data = data; + return rlcmac_prim; +} + +/* L1CTL-PDCH_DATA.req */ +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_pdch_data_req(uint8_t ts_nr, uint32_t fn, + uint8_t *data, uint8_t data_len) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_REQUEST, data_len); + rlcmac_prim->l1ctl.pdch_data_req.fn = fn; + rlcmac_prim->l1ctl.pdch_data_req.ts_nr = ts_nr; + rlcmac_prim->l1ctl.pdch_data_req.data_len = data_len; + rlcmac_prim->l1ctl.pdch_data_req.data = data; + return rlcmac_prim; +} + +/* L1CTL-PDCH_DATA.ind */ +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(uint8_t ts_nr, uint32_t fn, + uint8_t rx_lev, uint16_t ber10k, int16_t ci_cb, uint8_t *data, uint8_t data_len) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_INDICATION, data_len); + rlcmac_prim->l1ctl.pdch_data_ind.fn = fn; + rlcmac_prim->l1ctl.pdch_data_ind.ts_nr = ts_nr; + rlcmac_prim->l1ctl.pdch_data_ind.rx_lev = rx_lev; + rlcmac_prim->l1ctl.pdch_data_ind.ber10k = ber10k; + rlcmac_prim->l1ctl.pdch_data_ind.ci_cb = ci_cb; + rlcmac_prim->l1ctl.pdch_data_ind.data_len = data_len; + rlcmac_prim->l1ctl.pdch_data_ind.data = data; + return rlcmac_prim; +} + +/* L1CTL-PDCH_RTS.ind */ +struct osmo_gprs_rlcmac_prim *osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(uint8_t ts_nr, uint32_t fn, uint8_t usf) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_PDCH_RTS, PRIM_OP_INDICATION, 0); + rlcmac_prim->l1ctl.pdch_rts_ind.fn = fn; + rlcmac_prim->l1ctl.pdch_rts_ind.ts_nr = ts_nr; + rlcmac_prim->l1ctl.pdch_rts_ind.usf = usf; + return rlcmac_prim; +} + +/* L1CTL-CFG_DL_TBF.req */ +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_cfg_dl_tbf_req(uint8_t tbf_nr, uint8_t slotmask, uint8_t dl_tfi) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, PRIM_OP_REQUEST, 0); + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tbf_nr = tbf_nr; + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_slotmask = slotmask; + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tfi = dl_tfi; + return rlcmac_prim; +} + +/* L1CTL-CFG_UL_TBF.req */ +struct osmo_gprs_rlcmac_prim *gprs_rlcmac_prim_alloc_l1ctl_cfg_ul_tbf_req(uint8_t ul_tbf_nr, uint8_t ul_slotmask) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + rlcmac_prim = rlcmac_prim_l1ctl_alloc(OSMO_GPRS_RLCMAC_L1CTL_CFG_UL_TBF, PRIM_OP_REQUEST, 0); + rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_tbf_nr = ul_tbf_nr; + rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_slotmask = ul_slotmask; + return rlcmac_prim; +} + int gprs_rlcmac_prim_handle_unsupported(struct osmo_gprs_rlcmac_prim *rlcmac_prim) { LOGRLCMAC(LOGL_ERROR, "Unsupported rlcmac_prim! %s\n", osmo_gprs_rlcmac_prim_name(rlcmac_prim)); @@ -321,6 +435,47 @@ return rc; }
+static int rlcmac_prim_handle_l1ctl_pdch_rts_ind(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc = gprs_rlcmac_prim_handle_unsupported(rlcmac_prim); + rc = 1; /* msg owned (freed) */ + return rc; +} + +static int rlcmac_prim_handle_l1ctl_pdch_data_ind(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc = gprs_rlcmac_prim_handle_unsupported(rlcmac_prim); + rc = 1; /* msg owned (freed) */ + return rc; +} + +static int rlcmac_prim_handle_l1ctl_ccch_data_ind(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc = gprs_rlcmac_prim_handle_unsupported(rlcmac_prim); + rc = 1; /* msg owned (freed) */ + return rc; +} + +static int gprs_rlcmac_prim_l1ctl_lower_up(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc; + + switch (OSMO_PRIM_HDR(&rlcmac_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_RTS, PRIM_OP_INDICATION): + rc = rlcmac_prim_handle_l1ctl_pdch_rts_ind(rlcmac_prim); + break; + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_PDCH_DATA, PRIM_OP_INDICATION): + rc = rlcmac_prim_handle_l1ctl_pdch_data_ind(rlcmac_prim); + break; + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CCCH_DATA, PRIM_OP_INDICATION): + rc = rlcmac_prim_handle_l1ctl_ccch_data_ind(rlcmac_prim); + break; + default: + rc = -ENOTSUP; + } + return rc; +} + int osmo_gprs_rlcmac_prim_lower_up(struct osmo_gprs_rlcmac_prim *rlcmac_prim) { OSMO_ASSERT(g_ctx); @@ -331,10 +486,9 @@ LOGRLCMAC(LOGL_INFO, "Rx from lower layers: %s\n", osmo_gprs_rlcmac_prim_name(rlcmac_prim));
switch (rlcmac_prim->oph.sap) { - // TODO - //case OSMO_GPRS_LLC_SAP_GRR: - // OSMO_ASSERT(g_ctx->location == OSMO_GPRS_LLC_LOCATION_MS); - // rc = gprs_rlcmac_prim_lower_up_grr(rlcmac_prim); + case OSMO_GPRS_RLCMAC_SAP_L1CTL: + rc = gprs_rlcmac_prim_l1ctl_lower_up(rlcmac_prim); + break; default: rc = -EINVAL; } diff --git a/tests/rlcmac/Makefile.am b/tests/rlcmac/Makefile.am index 9ea8f16..949aed6 100644 --- a/tests/rlcmac/Makefile.am +++ b/tests/rlcmac/Makefile.am @@ -11,6 +11,7 @@ check_PROGRAMS = \ csn1_ts_44_018_test \ csn1_ts_44_060_test \ + rlcmac_prim_test \ $(NULL)
EXTRA_DIST = \ @@ -18,6 +19,8 @@ csn1_ts_44_018_test.err \ csn1_ts_44_060_test.ok \ csn1_ts_44_060_test.err \ + rlcmac_prim_test.ok \ + rlcmac_prim_test.err \ $(NULL)
# Common LDADD entries @@ -32,3 +35,6 @@
csn1_ts_44_060_test_SOURCES = csn1_ts_44_060_test.c csn1_ts_44_060_test_LDADD = $(LDADD) + +rlcmac_prim_test_SOURCES = rlcmac_prim_test.c +rlcmac_prim_test_LDADD = $(LDADD) diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c new file mode 100644 index 0000000..9347b01 --- /dev/null +++ b/tests/rlcmac/rlcmac_prim_test.c @@ -0,0 +1,211 @@ +/* rlcmac_prim_test.c + * + * (C) 2023 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * + * 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. + */ + +#include <stdint.h> +#include <stdio.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/msgb.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/gprs/rlcmac/rlcmac.h> +#include <osmocom/gprs/rlcmac/gre.h> + +static void *tall_ctx = NULL; + +/** +MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: GPRS Mobility Management + Address field SAPI: LLGMM + 0... .... = Protocol Discriminator_bit: OK + .0.. .... = Command/Response bit: DownLink/UpLink = Response/Command + .... 0001 = SAPI: GPRS Mobility Management (1) + Unconfirmed Information format - UI: UI format: 0x6, Spare bits: 0x0, N(U): 0, E bit: non encrypted frame, PM bit: FCS covers only the frame header and first N202 octets of the information field + 110. .... .... .... = UI format: 0x6 + ...0 0... .... .... = Spare bits: 0x0 + .... .000 0000 00.. = N(U): 0 + .... .... .... ..0. = E bit: non encrypted frame + .... .... .... ...0 = PM bit: FCS covers only the frame header and first N202 octets of the information field + FCS: 0xf218e2 (correct) +GSM A-I/F DTAP - Attach Request + Protocol Discriminator: GPRS mobility management messages (8) + DTAP GPRS Mobility Management Message Type: Attach Request (0x01) + MS Network Capability + Attach Type + Ciphering Key Sequence Number + DRX Parameter + Mobile Identity - IMSI (262420000000017) + Routing Area Identification - Old routing area identification - RAI: 262-42-27780-68 + MS Radio Access Capability +*/ +static uint8_t pdu_llc_gmm_att_req[] = { + 0x01, 0xc0, 0x00, 0x08, 0x01, 0x01, 0xd5, 0x71, 0x00, 0x00, 0x08, 0x29, 0x26, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x71, 0x62, 0xf2, 0x24, 0x6c, 0x84, 0x44, 0x04, + 0x11, 0xe5, 0x10, 0x00, 0xe2, 0x18, 0xf2 +}; + +/** +GSM CCCH - Immediate Assignment + L2 Pseudo Length + 0010 11.. = L2 Pseudo Length value: 11 + .... 0110 = Protocol discriminator: Radio Resources Management messages (0x6) + .... 0110 = Protocol discriminator: Radio Resources Management messages (0x6) + 0000 .... = Skip Indicator: No indication of selected PLMN (0) + Message Type: Immediate Assignment + Page Mode + .... 0000 = Page Mode: Normal paging (0) + Dedicated mode or TBF + 0001 .... = Dedicated mode or TBF: This message assigns an uplink TBF or is the second message of two in a two-message assignment of an uplink or downlink TBF (1) + Packet Channel Description + 0000 1... = Channel Type: 1 + .... .111 = Timeslot: 7 + 111. .... = Training Sequence: 7 + .... .0.. = Spare: 0x00 + .... ..11 0110 0111 = Single channel ARFCN: 871 + Request Reference + Random Access Information (RA): 120 + 0000 1... = T1': 1 + .... .001 011. .... = T3: 11 + ...0 1011 = T2: 11 + [RFN: 1337] + Timing Advance + Timing advance value: 0 + Mobile Allocation + Length: 0 + IA Rest Octets + H... .... = First Discriminator Bit: High + .H.. .... = Second Discriminator Bit: High + ..0. .... = Discriminator Bit: Packet Assignment + ...0 .... = Discriminator Bit: Packet Uplink Assignment + Packet Uplink Assignment + .... 1... = Packet Uplink Assignment: Normal + .... .000 00.. .... = TFI_Assignment: 0 + ..0. .... = Polling: no action is required from MS + ...0 .... = Allocation Type: Dynamic Allocation (mandatory after Rel-4) + .... 000. = USF: 0 + .... ...0 = USF_granularity: the mobile station shall transmit one RLC/MAC block + 0... .... = P0: Not Present + .01. .... = Channel_Coding_Command: CS-2 (1) + ...1 .... = TLLI_Block_Channel_Coding: mobile station shall use coding scheme as specified by the corresponding CHANNEL CODING COMMAND or EGPRS CHANNEL CODING COMMAND field + .... 0... = Alpha: Not Present + .... .000 00.. .... = Gamma: 0 dB (0) + ..0. .... = Timing Advance Index: Not Present + ...0 .... = TBF Starting Time: Not Present + .... L... = Additions in R99: Not Present + .... .L.. = Additions in Rel-6: Not Present + .... ..L. = Additions in Rel-10: Not Present + .... ...L = Additions in Rel-13: Not Present + Padding Bits: default padding +*/ +static uint8_t ccch_imm_ass_pkt_ul_tbf_normal[] = { + 0x2d, 0x06, 0x3f, 0x10, 0x0f, 0xe3, 0x67, 0x78, 0x09, 0x6b, + 0x00, 0x00, 0xc8, 0x00, 0x30, 0x0b, + 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b +}; + +static int test_rlcmac_prim_up_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim); + + switch (rlcmac_prim->oph.sap) { + case OSMO_GPRS_RLCMAC_SAP_GMMRR: + printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, rlcmac_prim->gmmrr.page_ind.tlli); + break; + case OSMO_GPRS_RLCMAC_SAP_GRR: + printf("%s(): Rx %s TLLI=0x%08x SAPI=%s ll=[%s]\n", __func__, pdu_name, + rlcmac_prim->grr.tlli, + get_value_string(osmo_gprs_rlcmac_llc_sapi_names, rlcmac_prim->grr.unitdata_req.sapi), + osmo_hexdump(rlcmac_prim->grr.ll_pdu, rlcmac_prim->grr.ll_pdu_len)); + break; + default: + printf("%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return 0; +} + +static int test_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim); + + switch (rlcmac_prim->oph.sap) { + case OSMO_GPRS_RLCMAC_SAP_L1CTL: + printf("%s(): Rx %s\n", __func__, pdu_name); + break; + default: + printf("%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return 0; +} + +void prepare_test(void) +{ + int rc; + rc = osmo_gprs_rlcmac_init(OSMO_GPRS_RLCMAC_LOCATION_MS); + OSMO_ASSERT(rc == 0); + + osmo_gprs_rlcmac_prim_set_up_cb(test_rlcmac_prim_up_cb, NULL); + osmo_gprs_rlcmac_prim_set_down_cb(test_rlcmac_prim_down_cb, NULL); +} + +static void test_ul_tbf_attach(void) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + int rc; + + printf("=== %s start ===\n", __func__); + prepare_test(); + uint32_t tlli = 0x2342; + + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req, + sizeof(pdu_llc_gmm_att_req)); + rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM; + rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim); + + OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN); + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + + /* This now fails because it's not yet implemented: */ + OSMO_ASSERT(rc != 0); + printf("=== %s end ===\n", __func__); +} + +static const struct log_info_cat test_log_categories[] = { }; +static const struct log_info test_log_info = { + .cat = test_log_categories, + .num_cat = ARRAY_SIZE(test_log_categories), +}; + +int main(int argc, char *argv[]) +{ + tall_ctx = talloc_named_const(NULL, 1, __FILE__); + + osmo_init_logging2(tall_ctx, &test_log_info); + log_parse_category_mask(osmo_stderr_target, "DLGLOBAL,1:"); + osmo_fsm_log_addr(false); + + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + log_set_print_level(osmo_stderr_target, 1); + log_set_use_color(osmo_stderr_target, 0); + + test_ul_tbf_attach(); + + talloc_free(tall_ctx); +} diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err new file mode 100644 index 0000000..f9268b1 --- /dev/null +++ b/tests/rlcmac/rlcmac_prim_test.err @@ -0,0 +1,4 @@ +DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request +DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly +DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication +DLGLOBAL ERROR Unsupported rlcmac_prim! L1CTL-CCCH_DATA.indication diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok new file mode 100644 index 0000000..3deb5e9 --- /dev/null +++ b/tests/rlcmac/rlcmac_prim_test.ok @@ -0,0 +1,2 @@ +=== test_ul_tbf_attach start === +=== test_ul_tbf_attach end === diff --git a/tests/testsuite.at b/tests/testsuite.at index 87e95b6..e27a320 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -43,6 +43,13 @@ AT_CHECK([$abs_top_builddir/tests/rlcmac/csn1_ts_44_060_test], [0], [expout], [experr]) AT_CLEANUP
+AT_SETUP([rlcmac/rlcmac_prim]) +AT_KEYWORDS([rlcmac rlcmac_prim]) +cat $abs_srcdir/rlcmac/rlcmac_prim_test.ok > expout +cat $abs_srcdir/rlcmac/rlcmac_prim_test.err > experr +AT_CHECK([$abs_top_builddir/tests/rlcmac/rlcmac_prim_test], [0], [expout], [experr]) +AT_CLEANUP + AT_SETUP([sndcp/sndcp_prim]) AT_KEYWORDS([sndcp sndcp_prim]) cat $abs_srcdir/sndcp/sndcp_prim_test.ok > expout