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(a)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
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-gprs/+/31177
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I3d97425ec75059ceae983de869419230e8c4df01
Gerrit-Change-Number: 31177
Gerrit-PatchSet: 10
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: neels <nhofmeyr(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged