pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31286 )
Change subject: rlcmac: Introduce DL TBF creation through PCH ImmAss ......................................................................
rlcmac: Introduce DL TBF creation through PCH ImmAss
This patch only introduces the gprs_rlcmac_dl_tbf subclass and allocates/frees it based on PCH ImmAss, and adds initial paths for received blocks. It also provides a unit test to showcase the scenario.
Change-Id: I7f98e3456ef35d80becdad3481afeb771457b0ef --- M include/osmocom/gprs/rlcmac/Makefile.am M include/osmocom/gprs/rlcmac/coding_scheme.h M include/osmocom/gprs/rlcmac/gre.h M include/osmocom/gprs/rlcmac/rlcmac.h M include/osmocom/gprs/rlcmac/rlcmac_private.h A include/osmocom/gprs/rlcmac/tbf_dl.h A include/osmocom/gprs/rlcmac/tbf_dl_fsm.h M include/osmocom/gprs/rlcmac/types_private.h M src/rlcmac/Makefile.am M src/rlcmac/coding_scheme.c M src/rlcmac/gre.c M src/rlcmac/misc.c M src/rlcmac/rlcmac.c M src/rlcmac/rlcmac_prim.c A src/rlcmac/tbf_dl.c A src/rlcmac/tbf_dl_fsm.c M tests/rlcmac/Makefile.am M tests/rlcmac/rlcmac_prim_test.c M tests/rlcmac/rlcmac_prim_test.err M tests/rlcmac/rlcmac_prim_test.ok 20 files changed, 722 insertions(+), 8 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/rlcmac/Makefile.am b/include/osmocom/gprs/rlcmac/Makefile.am index 3f04ee3..e91f342 100644 --- a/include/osmocom/gprs/rlcmac/Makefile.am +++ b/include/osmocom/gprs/rlcmac/Makefile.am @@ -10,6 +10,8 @@ rlcmac_private.h \ sched.h \ tbf.h \ + tbf_dl.h \ + tbf_dl_fsm.h \ tbf_ul.h \ tbf_ul_fsm.h \ tbf_ul_ass_fsm.h \ diff --git a/include/osmocom/gprs/rlcmac/coding_scheme.h b/include/osmocom/gprs/rlcmac/coding_scheme.h index 31692a5..5b71e73 100644 --- a/include/osmocom/gprs/rlcmac/coding_scheme.h +++ b/include/osmocom/gprs/rlcmac/coding_scheme.h @@ -61,6 +61,7 @@ uint8_t gprs_rlcmac_mcs_chan_code(enum gprs_rlcmac_coding_scheme cs);
enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_by_size_ul(unsigned size); +enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_by_size_dl(unsigned size); enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_gprs_by_num(unsigned num); enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_egprs_by_num(unsigned num); bool gprs_rlcmac_mcs_is_valid(enum gprs_rlcmac_coding_scheme cs); diff --git a/include/osmocom/gprs/rlcmac/gre.h b/include/osmocom/gprs/rlcmac/gre.h index ea50ddb..ca5f773 100644 --- a/include/osmocom/gprs/rlcmac/gre.h +++ b/include/osmocom/gprs/rlcmac/gre.h @@ -4,6 +4,7 @@ #include <osmocom/gprs/rlcmac/rlcmac.h> #include <osmocom/gprs/rlcmac/llc_queue.h>
+struct gprs_rlcmac_dl_tbf; struct gprs_rlcmac_ul_tbf;
struct gprs_rlcmac_entity { @@ -12,6 +13,7 @@
struct gprs_rlcmac_llc_queue *llc_queue;
+ struct gprs_rlcmac_dl_tbf *dl_tbf; struct gprs_rlcmac_ul_tbf *ul_tbf; };
diff --git a/include/osmocom/gprs/rlcmac/rlcmac.h b/include/osmocom/gprs/rlcmac/rlcmac.h index 2de5687..64a2073 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac.h +++ b/include/osmocom/gprs/rlcmac/rlcmac.h @@ -18,6 +18,7 @@ enum osmo_gprs_rlcmac_log_cat { OSMO_GPRS_RLCMAC_LOGC_RLCMAC, OSMO_GPRS_RLCMAC_LOGC_TBFUL, + OSMO_GPRS_RLCMAC_LOGC_TBFDL, _OSMO_GPRS_RLCMAC_LOGC_MAX, };
diff --git a/include/osmocom/gprs/rlcmac/rlcmac_private.h b/include/osmocom/gprs/rlcmac/rlcmac_private.h index f35b69a..36c634c 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac_private.h +++ b/include/osmocom/gprs/rlcmac/rlcmac_private.h @@ -28,6 +28,16 @@ struct gprs_rlcmac_ul_tbf_allocation_ts ts[8]; };
+struct gprs_rlcmac_dl_tbf_allocation_ts { + bool allocated; +}; + +struct gprs_rlcmac_dl_tbf_allocation { + uint8_t dl_tfi; + uint8_t num_ts; /* number of allocated TS */ + struct gprs_rlcmac_dl_tbf_allocation_ts ts[8]; +}; + extern int g_rlcmac_log_cat[_OSMO_GPRS_RLCMAC_LOGC_MAX];
#define LOGRLCMAC(lvl, fmt, args...) LOGP(g_rlcmac_log_cat[OSMO_GPRS_RLCMAC_LOGC_RLCMAC], lvl, fmt, ## args) @@ -56,13 +66,17 @@ struct llist_head gre_list; /* contains (struct gprs_rlcmac_entity)->entry */
uint8_t next_ul_tbf_nr; + uint8_t next_dl_tbf_nr; };
extern struct gprs_rlcmac_ctx *g_ctx;
/* rlcmac.c */ struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli); +struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi); int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia); +int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim, + enum gprs_rlcmac_coding_scheme cs);
/* rlcmac_prim.c */ int gprs_rlcmac_prim_call_up_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim); diff --git a/include/osmocom/gprs/rlcmac/tbf_dl.h b/include/osmocom/gprs/rlcmac/tbf_dl.h new file mode 100644 index 0000000..56b0e8c --- /dev/null +++ b/include/osmocom/gprs/rlcmac/tbf_dl.h @@ -0,0 +1,52 @@ +/* Downlink TBF, 3GPP TS 44.060 */ +#pragma once + +#include <inttypes.h> + +#include <osmocom/core/msgb.h> + +#include <osmocom/gprs/rlcmac/tbf.h> +#include <osmocom/gprs/rlcmac/tbf_dl_fsm.h> +#include <osmocom/gprs/rlcmac/coding_scheme.h> +#include <osmocom/gprs/rlcmac/sched.h> +#include <osmocom/gprs/rlcmac/rlcmac_private.h> + +struct gprs_rlcmac_dl_tbf { + struct gprs_rlcmac_tbf tbf; + struct gprs_rlcmac_tbf_dl_fsm_ctx state_fsm; + + /* Current TS/TFI/USF allocated by the PCU: */ + struct gprs_rlcmac_dl_tbf_allocation cur_alloc; +}; + +struct gprs_rlcmac_dl_tbf *gprs_rlcmac_dl_tbf_alloc(struct gprs_rlcmac_entity *gre); +void gprs_rlcmac_dl_tbf_free(struct gprs_rlcmac_dl_tbf *dl_tbf); + +int gprs_rlcmac_dl_tbf_configure_l1ctl(struct gprs_rlcmac_dl_tbf *dl_tbf); + +static inline struct gprs_rlcmac_tbf *dl_tbf_as_tbf(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + return &dl_tbf->tbf; +} + +static inline const struct gprs_rlcmac_tbf *dl_tbf_as_tbf_const(const struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + return &dl_tbf->tbf; +} + +static inline struct gprs_rlcmac_dl_tbf *tbf_as_dl_tbf(struct gprs_rlcmac_tbf *tbf) +{ + OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_TBF_DIR_DL); + return (struct gprs_rlcmac_dl_tbf *)tbf; +} + +static inline const struct gprs_rlcmac_dl_tbf *tbf_as_dl_tbf_const(struct gprs_rlcmac_tbf *tbf) +{ + OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_TBF_DIR_DL); + return (const struct gprs_rlcmac_dl_tbf *)tbf; +} + +#define LOGPTBFDL(dl_tbf, lvl, fmt, args...) \ + LOGP(g_rlcmac_log_cat[OSMO_GPRS_RLCMAC_LOGC_TBFUL], lvl, "TBF(DL:NR-%" PRIu8 ":TLLI-%08x) " fmt, \ + (dl_tbf)->tbf.nr, (dl_tbf)->tbf.gre->tlli, \ + ## args) diff --git a/include/osmocom/gprs/rlcmac/tbf_dl_fsm.h b/include/osmocom/gprs/rlcmac/tbf_dl_fsm.h new file mode 100644 index 0000000..5458b68 --- /dev/null +++ b/include/osmocom/gprs/rlcmac/tbf_dl_fsm.h @@ -0,0 +1,35 @@ +/* Uplink TBF, 3GPP TS 44.060 */ +#pragma once + +#include <osmocom/core/fsm.h> + +#include <osmocom/gprs/rlcmac/rlcmac_private.h> + +struct gprs_rlcmac_dl_tbf; + +enum gprs_rlcmac_tbf_dl_fsm_states { + GPRS_RLCMAC_TBF_DL_ST_NEW = 0, /* new created TBF */ + GPRS_RLCMAC_TBF_DL_ST_FLOW, /* RLC/MAC flow, resource needed */ + GPRS_RLCMAC_TBF_DL_ST_FINISHED, /* flow finished, wait for release */ +}; + +struct gprs_rlcmac_tbf_dl_fsm_ctx { + struct osmo_fsm_inst *fi; + union { /* back pointer. union used to easily access superclass from ctx */ + struct gprs_rlcmac_tbf *tbf; + struct gprs_rlcmac_dl_tbf *dl_tbf; + }; +}; + +enum tbf_dl_fsm_event { + GPRS_RLCMAC_TBF_DL_EV_LAST_DL_DATA_RECVD, + GPRS_RLCMAC_TBF_UL_EV_DL_ASS_COMPL, +}; + +int gprs_rlcmac_tbf_dl_fsm_init(void); +void gprs_rlcmac_tbf_dl_fsm_set_log_cat(int logcat); + +int gprs_rlcmac_tbf_dl_fsm_constructor(struct gprs_rlcmac_dl_tbf *dl_tbf); +void gprs_rlcmac_tbf_dl_fsm_destructor(struct gprs_rlcmac_dl_tbf *dl_tbf); + +enum gprs_rlcmac_tbf_dl_fsm_states gprs_rlcmac_tbf_dl_state(const struct gprs_rlcmac_dl_tbf *dl_tbf); diff --git a/include/osmocom/gprs/rlcmac/types_private.h b/include/osmocom/gprs/rlcmac/types_private.h index 10852cf..8450d08 100644 --- a/include/osmocom/gprs/rlcmac/types_private.h +++ b/include/osmocom/gprs/rlcmac/types_private.h @@ -3,6 +3,14 @@
#include <osmocom/gprs/rlcmac/types.h>
+/* TS 44.060 Section 10.4.7 Table 10.4.7.1: Payload Type field */ +enum gprs_rlcmac_payload_type { + GPRS_RLCMAC_PT_DATA_BLOCK = 0x0, + GPRS_RLCMAC_PT_CONTROL_BLOCK = 0x1, + GPRS_RLCMAC_PT_CONTROL_BLOCK_OPT = 0x2, + GPRS_RLCMAC_PT_RESERVED = 0x3 +}; + /* TS 44.060 Table 11.2.16.2 "ACCESS_TYPE" */ enum gprs_rlcmac_access_type { GPRS_RLCMAC_ACCESS_TYPE_2PHASE_ACC_REQ = 0, /* Two Phase Access Request */ diff --git a/src/rlcmac/Makefile.am b/src/rlcmac/Makefile.am index 6fca2b0..0612eaa 100644 --- a/src/rlcmac/Makefile.am +++ b/src/rlcmac/Makefile.am @@ -39,6 +39,8 @@ rlcmac_prim.c \ sched.c \ tbf.c \ + tbf_dl.c \ + tbf_dl_fsm.c \ tbf_ul.c \ tbf_ul_fsm.c \ tbf_ul_ass_fsm.c \ diff --git a/src/rlcmac/coding_scheme.c b/src/rlcmac/coding_scheme.c index 889e0ff..350cb0b 100644 --- a/src/rlcmac/coding_scheme.c +++ b/src/rlcmac/coding_scheme.c @@ -144,6 +144,27 @@ } }
+/* Same as UL. Sizes only change in EGPRS2 blocks, which we don't support */ +enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_by_size_dl(unsigned size) +{ + switch (size) { + case 23: return GPRS_RLCMAC_CS_1; + case 27: return GPRS_RLCMAC_MCS_1; + case 33: return GPRS_RLCMAC_MCS_2; + case 34: return GPRS_RLCMAC_CS_2; + case 40: return GPRS_RLCMAC_CS_3; + case 42: return GPRS_RLCMAC_MCS_3; + case 49: return GPRS_RLCMAC_MCS_4; + case 54: return GPRS_RLCMAC_CS_4; + case 61: return GPRS_RLCMAC_MCS_5; + case 79: return GPRS_RLCMAC_MCS_6; + case 119: return GPRS_RLCMAC_MCS_7; + case 143: return GPRS_RLCMAC_MCS_8; + case 155: return GPRS_RLCMAC_MCS_9; + default: return GPRS_RLCMAC_CS_UNKNOWN; + } +} + enum gprs_rlcmac_coding_scheme gprs_rlcmac_mcs_get_gprs_by_num(unsigned num) { if (num < 1 || num > 4) diff --git a/src/rlcmac/gre.c b/src/rlcmac/gre.c index 3d8ba08..40cd585 100644 --- a/src/rlcmac/gre.c +++ b/src/rlcmac/gre.c @@ -24,6 +24,7 @@ #include <osmocom/gprs/rlcmac/rlcmac.h> #include <osmocom/gprs/rlcmac/rlcmac_prim.h> #include <osmocom/gprs/rlcmac/rlcmac_private.h> +#include <osmocom/gprs/rlcmac/tbf_dl.h> #include <osmocom/gprs/rlcmac/tbf_ul_fsm.h> #include <osmocom/gprs/rlcmac/tbf_ul.h> #include <osmocom/gprs/rlcmac/gre.h> @@ -58,6 +59,7 @@ if (!gre) return;
+ gprs_rlcmac_dl_tbf_free(gre->dl_tbf); gprs_rlcmac_ul_tbf_free(gre->ul_tbf); gprs_rlcmac_llc_queue_free(gre->llc_queue); llist_del(&gre->entry); diff --git a/src/rlcmac/misc.c b/src/rlcmac/misc.c index 4edc2b9..7317bd1 100644 --- a/src/rlcmac/misc.c +++ b/src/rlcmac/misc.c @@ -18,6 +18,7 @@ #include <osmocom/core/utils.h> #include <osmocom/core/logging.h> #include <osmocom/gprs/rlcmac/rlcmac.h> +#include <osmocom/gprs/rlcmac/tbf_dl_fsm.h> #include <osmocom/gprs/rlcmac/tbf_ul_fsm.h> #include <osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h>
@@ -30,8 +31,15 @@ OSMO_ASSERT(logc < _OSMO_GPRS_RLCMAC_LOGC_MAX); g_rlcmac_log_cat[logc] = logc_num;
- if (logc == OSMO_GPRS_RLCMAC_LOGC_TBFUL) { + switch (logc) { + case OSMO_GPRS_RLCMAC_LOGC_TBFUL: gprs_rlcmac_tbf_ul_fsm_set_log_cat(logc_num); gprs_rlcmac_tbf_ul_ass_fsm_set_log_cat(logc_num); + break; + case OSMO_GPRS_RLCMAC_LOGC_TBFDL: + gprs_rlcmac_tbf_dl_fsm_set_log_cat(logc_num); + break; + default: + break; } } diff --git a/src/rlcmac/rlcmac.c b/src/rlcmac/rlcmac.c index 3310950..19d9944 100644 --- a/src/rlcmac/rlcmac.c +++ b/src/rlcmac/rlcmac.c @@ -29,8 +29,11 @@ #include <osmocom/gprs/rlcmac/tbf_ul_fsm.h> #include <osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h> #include <osmocom/gprs/rlcmac/gre.h> +#include <osmocom/gprs/rlcmac/tbf_dl.h> #include <osmocom/gprs/rlcmac/tbf_ul.h> #include <osmocom/gprs/rlcmac/csn1_defs.h> +#include <osmocom/gprs/rlcmac/rlc.h> +#include <osmocom/gprs/rlcmac/types_private.h>
#define GPRS_CODEL_SLOW_INTERVAL_MS 4000
@@ -73,6 +76,11 @@ osmo_tdefs_reset(g_ctx->T_defs);
if (first_init) { + rc = gprs_rlcmac_tbf_dl_fsm_init(); + if (rc != 0) { + TALLOC_FREE(g_ctx); + return rc; + } rc = gprs_rlcmac_tbf_ul_fsm_init(); if (rc != 0) { TALLOC_FREE(g_ctx); @@ -114,6 +122,20 @@ return NULL; }
+struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi) +{ + struct gprs_rlcmac_entity *gre; + + llist_for_each_entry(gre, &g_ctx->gre_list, entry) { + if (!gre->dl_tbf) + continue; + if (gre->dl_tbf->cur_alloc.dl_tfi != dl_tfi) + continue; + return gre->dl_tbf; + } + return NULL; +} + static int gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(uint8_t ts_nr, const struct gsm48_imm_ass *ia, const IA_RestOctets_t *iaro) { int rc = -ENOENT; @@ -139,6 +161,40 @@ return rc; }
+static int gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(uint8_t ts_nr, const struct gsm48_imm_ass *ia, const IA_RestOctets_t *iaro) +{ + int rc; + struct gprs_rlcmac_entity *gre; + struct gprs_rlcmac_dl_tbf *dl_tbf; + const Packet_Downlink_ImmAssignment_t *pkdlass; + + if (iaro->UnionType == 1) { + /* TODO */ + return -ENOENT; + } + + pkdlass = &iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Downlink_ImmAssignment; + + gre = gprs_rlcmac_find_entity_by_tlli(pkdlass->TLLI); + if (!gre) { + LOGRLCMAC(LOGL_NOTICE, "Got IMM_ASS (DL_TBF) for unknown TLLI=0x%08x\n", pkdlass->TLLI); + return -ENOENT; + } + + LOGGRE(gre, LOGL_INFO, "Got PCH IMM_ASS (DL_TBF): DL_TFI=%u TS=%u\n", + pkdlass->TFI_ASSIGNMENT, ts_nr); + dl_tbf = gprs_rlcmac_dl_tbf_alloc(gre); + dl_tbf->cur_alloc.dl_tfi = pkdlass->TFI_ASSIGNMENT; + dl_tbf->cur_alloc.ts[ts_nr].allocated = true; + + /* replace old DL TBF with new one: */ + gprs_rlcmac_dl_tbf_free(gre->dl_tbf); + gre->dl_tbf = dl_tbf; + + rc = osmo_fsm_inst_dispatch(dl_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_DL_ASS_COMPL, NULL); + return rc; +} + int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia) { int rc; @@ -171,7 +227,7 @@ rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, ia, &iaro); break; case 1: /* iaro.u.ll.lh0x.MultiBlock_PktDlAss.* (IA_MultiBlock_PktDlAss_t) */ - /* TODO: Alloc DL TBF */ + rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, ia, &iaro); break; } /* TODO: iaro.u.lh.AdditionsR13.* (IA_AdditionsR13_t) */ @@ -204,7 +260,7 @@ } break; case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Downlink_ImmAssignment* (Packet_Downlink_ImmAssignment_t) */ - /* TODO: Alloc DL TBF */ + rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, ia, &iaro); break; } break; @@ -216,3 +272,71 @@
return rc; } + +static int gprs_rlcmac_handle_gprs_dl_ctrl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + struct bitvec *bv; + RlcMacDownlink_t *dl_ctrl_block; + size_t max_len = gprs_rlcmac_mcs_max_bytes_dl(GPRS_RLCMAC_CS_1); + int rc; + + bv = bitvec_alloc(max_len, g_ctx); + OSMO_ASSERT(bv); + bitvec_unpack(bv, rlcmac_prim->l1ctl.pdch_data_ind.data); + + dl_ctrl_block = (RlcMacDownlink_t *)talloc_zero(g_ctx, RlcMacDownlink_t); + OSMO_ASSERT(dl_ctrl_block); + rc = osmo_gprs_rlcmac_decode_downlink(bv, dl_ctrl_block); + if (rc < 0) { + LOGRLCMAC(LOGL_NOTICE, "Failed decoding dl ctrl block: %s\n", + osmo_hexdump(rlcmac_prim->l1ctl.pdch_data_ind.data, + rlcmac_prim->l1ctl.pdch_data_ind.data_len)); + goto free_ret; + } + + LOGRLCMAC(LOGL_NOTICE, "TODO: handle decoded dl ctrl block!\n"); + +free_ret: + talloc_free(dl_ctrl_block); + bitvec_free(bv); + return rc; +} + +static int gprs_rlcmac_handle_gprs_dl_data_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + const struct gprs_rlcmac_rlc_dl_data_header *data_hdr = (const struct gprs_rlcmac_rlc_dl_data_header *)rlcmac_prim->l1ctl.pdch_data_ind.data; + struct gprs_rlcmac_dl_tbf *dl_tbf; + + dl_tbf = gprs_rlcmac_find_dl_tbf_by_tfi(data_hdr->tfi); + if (!dl_tbf) { + LOGPTBFDL(dl_tbf, LOGL_INFO, "Rx DL data for unknown dl_tfi=%u\n", data_hdr->tfi); + return -ENOENT; + } + LOGPTBFDL(dl_tbf, LOGL_DEBUG, "Rx new DL data\n"); + return 0; +} + +int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim, + enum gprs_rlcmac_coding_scheme cs) +{ + const struct gprs_rlcmac_rlc_dl_data_header *data_hdr = (const struct gprs_rlcmac_rlc_dl_data_header *)rlcmac_prim->l1ctl.pdch_data_ind.data; + /* Check block content (data vs ctrl) based on Payload Type: TS 44.060 10.4.7 */ + switch ((enum gprs_rlcmac_payload_type)data_hdr->pt) { + case GPRS_RLCMAC_PT_DATA_BLOCK: + /* "Contains an RLC data block" */ + return gprs_rlcmac_handle_gprs_dl_data_block(rlcmac_prim); + case GPRS_RLCMAC_PT_CONTROL_BLOCK: + /* "Contains an RLC/MAC control block that does not include the optional octets of the RLC/MAC + * control header" */ + return gprs_rlcmac_handle_gprs_dl_ctrl_block(rlcmac_prim); + case GPRS_RLCMAC_PT_CONTROL_BLOCK_OPT: + /* Contains an RLC/MAC control block that includes the optional first octet of the RLC/MAC + * control header" */ + return gprs_rlcmac_handle_gprs_dl_ctrl_block(rlcmac_prim); + case GPRS_RLCMAC_PT_RESERVED: /* Reserved. In this version of the protocol, the mobile station shall ignore all fields of the + * RLC/MAC block except for the USF field */ + return 0; + default: + OSMO_ASSERT(0); + } +} diff --git a/src/rlcmac/rlcmac_prim.c b/src/rlcmac/rlcmac_prim.c index 954f954..1707578 100644 --- a/src/rlcmac/rlcmac_prim.c +++ b/src/rlcmac/rlcmac_prim.c @@ -37,6 +37,7 @@ #include <osmocom/gprs/rlcmac/rlcmac_prim.h> #include <osmocom/gprs/rlcmac/rlcmac_private.h> #include <osmocom/gprs/rlcmac/gre.h> +#include <osmocom/gprs/rlcmac/tbf_dl.h> #include <osmocom/gprs/rlcmac/tbf_ul.h> #include <osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h>
@@ -466,9 +467,27 @@
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; + enum gprs_rlcmac_coding_scheme cs = gprs_rlcmac_mcs_get_by_size_dl(rlcmac_prim->l1ctl.pdch_data_ind.data_len); + + if (cs == GPRS_RLCMAC_CS_UNKNOWN) { + LOGRLCMAC(LOGL_ERROR, "Dropping DL data block with invalid length %u: %s\n", + rlcmac_prim->l1ctl.pdch_data_ind.data_len, + osmo_hexdump(rlcmac_prim->l1ctl.pdch_data_ind.data, + rlcmac_prim->l1ctl.pdch_data_ind.data_len)); + return -EINVAL; + } + + if (gprs_rlcmac_mcs_is_gprs(cs)) + return gprs_rlcmac_handle_gprs_dl_block(rlcmac_prim, cs); + + if (gprs_rlcmac_mcs_is_edge(cs)) { + LOGRLCMAC(LOGL_NOTICE, "RX EGPRS DL data block NOT SUPPORTED\n"); + return -ENOTSUP; + } + + /* Should never be reached. */ + OSMO_ASSERT(0); + return -EINVAL; }
static int rlcmac_prim_handle_l1ctl_ccch_data_ind(struct osmo_gprs_rlcmac_prim *rlcmac_prim) diff --git a/src/rlcmac/tbf_dl.c b/src/rlcmac/tbf_dl.c new file mode 100644 index 0000000..ae6e7ac --- /dev/null +++ b/src/rlcmac/tbf_dl.c @@ -0,0 +1,86 @@ +/* Downlink TBF as per 3GPP TS 44.064 */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ +#include <osmocom/core/logging.h> + +#include <osmocom/gprs/rlcmac/tbf_dl.h> +#include <osmocom/gprs/rlcmac/gre.h> + +struct gprs_rlcmac_dl_tbf *gprs_rlcmac_dl_tbf_alloc(struct gprs_rlcmac_entity *gre) +{ + struct gprs_rlcmac_dl_tbf *dl_tbf; + int rc; + + dl_tbf = talloc_zero(gre, struct gprs_rlcmac_dl_tbf); + if (!dl_tbf) + return NULL; + + gprs_rlcmac_tbf_constructor(dl_tbf_as_tbf(dl_tbf), GPRS_RLCMAC_TBF_DIR_DL, gre); + + rc = gprs_rlcmac_tbf_dl_fsm_constructor(dl_tbf); + if (rc < 0) + goto err_tbf_destruct; + + dl_tbf->tbf.nr = g_ctx->next_dl_tbf_nr++; + + return dl_tbf; +err_tbf_destruct: + gprs_rlcmac_tbf_destructor(dl_tbf_as_tbf(dl_tbf)); + talloc_free(dl_tbf); + return NULL; +} + +void gprs_rlcmac_dl_tbf_free(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + if (!dl_tbf) + return; + + //gprs_rlcmac_tbf_dl_fsm_destructor(dl_tbf); + + gprs_rlcmac_tbf_destructor(dl_tbf_as_tbf(dl_tbf)); + talloc_free(dl_tbf); +} + + +static uint8_t dl_tbf_dl_slotmask(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + uint8_t i; + uint8_t dl_slotmask = 0; + + for (i = 0; i < 8; i++) { + if (dl_tbf->cur_alloc.ts[i].allocated) + dl_slotmask |= (1 << i); + } + + return dl_slotmask; +} + +int gprs_rlcmac_dl_tbf_configure_l1ctl(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + uint8_t dl_slotmask = dl_tbf_dl_slotmask(dl_tbf); + + LOGPTBFDL(dl_tbf, LOGL_INFO, "Send L1CTL-CF_DL_TBF.req dl_slotmask=0x%02x dl_tfi=%u\n", + dl_slotmask, dl_tbf->cur_alloc.dl_tfi); + rlcmac_prim = gprs_rlcmac_prim_alloc_l1ctl_cfg_dl_tbf_req(dl_tbf->tbf.nr, + dl_slotmask, + dl_tbf->cur_alloc.dl_tfi); + return gprs_rlcmac_prim_call_down_cb(rlcmac_prim); +} diff --git a/src/rlcmac/tbf_dl_fsm.c b/src/rlcmac/tbf_dl_fsm.c new file mode 100644 index 0000000..e4a4cf2 --- /dev/null +++ b/src/rlcmac/tbf_dl_fsm.c @@ -0,0 +1,164 @@ +/* TBF as per 3GPP TS 44.064 */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + * + */ + +#include <talloc.h> +#include <osmocom/core/tdef.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/gprs/rlcmac/tbf_dl_fsm.h> +#include <osmocom/gprs/rlcmac/tbf_dl.h> +#include <osmocom/gprs/rlcmac/gre.h> + +#define X(s) (1 << (s)) + +static const struct value_string tbf_dl_fsm_event_names[] = { + { GPRS_RLCMAC_TBF_DL_EV_LAST_DL_DATA_RECVD, "LAST_DL_DATA_RECVD" }, + { GPRS_RLCMAC_TBF_UL_EV_DL_ASS_COMPL, "DL_ASS_COMPL" }, + { 0, NULL } +}; + +static const struct osmo_tdef_state_timeout tbf_dl_fsm_timeouts[32] = { + [GPRS_RLCMAC_TBF_DL_ST_NEW] = { }, + [GPRS_RLCMAC_TBF_DL_ST_FLOW] = { }, + [GPRS_RLCMAC_TBF_DL_ST_FINISHED] = { }, +}; + +/* Transition to a state, using the T timer defined in tbf_fsm_timeouts. + * The actual timeout value is in turn obtained from conn->T_defs. + * Assumes local variable fi exists. */ + #define tbf_dl_fsm_state_chg(fi, NEXT_STATE) \ + osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, \ + tbf_dl_fsm_timeouts, \ + g_ctx->T_defs, \ + -1) + +static void st_new(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_dl_fsm_ctx *)fi->priv; + switch (event) { + case GPRS_RLCMAC_TBF_UL_EV_DL_ASS_COMPL: + /* Configure DL TBF on the lower MAC side: */ + gprs_rlcmac_dl_tbf_configure_l1ctl(ctx->dl_tbf); + tbf_dl_fsm_state_chg(fi, GPRS_RLCMAC_TBF_DL_ST_FLOW); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_flow(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + //struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_dl_fsm_ctx *)fi->priv; + switch (event) { + case GPRS_RLCMAC_TBF_DL_EV_LAST_DL_DATA_RECVD: + tbf_dl_fsm_state_chg(fi, GPRS_RLCMAC_TBF_DL_ST_FINISHED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_finished(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + //struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_dl_fsm_ctx *)fi->priv; + switch (event) { + default: + OSMO_ASSERT(0); + } +} + +static struct osmo_fsm_state tbf_dl_fsm_states[] = { + [GPRS_RLCMAC_TBF_DL_ST_NEW] = { + .in_event_mask = + X(GPRS_RLCMAC_TBF_UL_EV_DL_ASS_COMPL), + .out_state_mask = + X(GPRS_RLCMAC_TBF_DL_ST_FLOW), + .name = "NEW", + .action = st_new, + }, + [GPRS_RLCMAC_TBF_DL_ST_FLOW] = { + .in_event_mask = + X(GPRS_RLCMAC_TBF_DL_EV_LAST_DL_DATA_RECVD), + .out_state_mask = + X(GPRS_RLCMAC_TBF_DL_ST_FINISHED), + .name = "FLOW", + .action = st_flow, + }, + [GPRS_RLCMAC_TBF_DL_ST_FINISHED] = { + .in_event_mask = 0, + .out_state_mask = 0, + .name = "FINISHED", + .action = st_finished, + }, +}; + +static int tbf_dl_fsm_timer_cb(struct osmo_fsm_inst *fi) +{ + //struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_dl_fsm_ctx *)fi->priv; + switch (fi->T) { + default: + OSMO_ASSERT(0); + } + return 0; +} + +static struct osmo_fsm tbf_dl_fsm = { + .name = "DL_TBF", + .states = tbf_dl_fsm_states, + .num_states = ARRAY_SIZE(tbf_dl_fsm_states), + .timer_cb = tbf_dl_fsm_timer_cb, + .log_subsys = DLGLOBAL, /* updated dynamically through gprs_rlcmac_tbf_dl_fsm_set_log_cat() */ + .event_names = tbf_dl_fsm_event_names, +}; + +int gprs_rlcmac_tbf_dl_fsm_init(void) +{ + return osmo_fsm_register(&tbf_dl_fsm); +} + +void gprs_rlcmac_tbf_dl_fsm_set_log_cat(int logcat) +{ + tbf_dl_fsm.log_subsys = logcat; +} + +int gprs_rlcmac_tbf_dl_fsm_constructor(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = &dl_tbf->state_fsm; + ctx->dl_tbf = dl_tbf; + ctx->fi = osmo_fsm_inst_alloc(&tbf_dl_fsm, dl_tbf, ctx, LOGL_INFO, NULL); + if (!ctx->fi) + return -ENODATA; + + return 0; +} + +void gprs_rlcmac_tbf_dl_fsm_destructor(struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = &dl_tbf->state_fsm; + osmo_fsm_inst_free(ctx->fi); + ctx->fi = NULL; +} + +enum gprs_rlcmac_tbf_dl_fsm_states gprs_rlcmac_tbf_dl_state(const struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + const struct gprs_rlcmac_tbf_dl_fsm_ctx *ctx = &dl_tbf->state_fsm; + return ctx->fi->state; +} diff --git a/tests/rlcmac/Makefile.am b/tests/rlcmac/Makefile.am index 949aed6..8d19656 100644 --- a/tests/rlcmac/Makefile.am +++ b/tests/rlcmac/Makefile.am @@ -1,5 +1,6 @@ AM_CFLAGS = \ -Wall \ + $(LIBOSMOGSM_CFLAGS) \ $(LIBOSMOCORE_CFLAGS) \ -I$(top_srcdir)/include/ \ $(NULL) @@ -24,10 +25,12 @@ $(NULL)
# Common LDADD entries +# libosmo-gprs-rlcmac.a is used below to access non-exported private symbols used in the test: LDADD = \ - $(LIBOSMOCORE_LIBS) \ + $(top_builddir)/src/rlcmac/.libs/libosmo-gprs-rlcmac.a \ $(top_builddir)/src/csn1/libosmo-csn1.la \ - $(top_builddir)/src/rlcmac/libosmo-gprs-rlcmac.la \ + $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCORE_LIBS) \ $(NULL)
csn1_ts_44_018_test_SOURCES = csn1_ts_44_018_test.c diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c index fa864f9..00f1740 100644 --- a/tests/rlcmac/rlcmac_prim_test.c +++ b/tests/rlcmac/rlcmac_prim_test.c @@ -24,6 +24,7 @@
#include <osmocom/gprs/rlcmac/rlcmac.h> #include <osmocom/gprs/rlcmac/gre.h> +#include <osmocom/gprs/rlcmac/rlc.h>
static void *tall_ctx = NULL;
@@ -118,6 +119,64 @@ 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b };
+/* +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 + 0011 .... = Dedicated mode or TBF: This message assigns a downlink TBF to the mobile station identified in the IA Rest Octets IE (3) + 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): 125 + 1000 0... = T1': 16 + .... .000 000. .... = T3: 0 + ...0 0000 = T2: 0 + [RFN: 21216] + Timing Advance + Timing advance value: 28 + Mobile Allocation + Length: 0 + IA Rest Octets + H... .... = First Discriminator Bit: High + .H.. .... = Second Discriminator Bit: High + ..0. .... = Discriminator Bit: Packet Assignment + ...1 .... = Discriminator Bit: Packet Downlink Assignment + Packet Downlink Assignment + .... 0000 0000 0000 0000 0000 0000 0000 0001 .... = TLLI: 0x00000001 + .... 1... = TFI Assignment (etc): Present + .... .000 00.. .... = TFI_Assignment: 0 + ..0. .... = RLC_Mode: RLC acknowledged mode + ...0 .... = Alpha: Not Present + .... 0000 0... .... = Gamma: 0 dB (0) + .0.. .... = Polling: no action is required from MS + ..0. .... = TA_Valid: the timing advance value is not valid + ...0 .... = Timing Advance Index: Not Present + .... 0... = TBF Starting Time: Not Present + .... .0.. = P0: Not Present + .... ..L. = Additions in R99: Not Present + .... ...L = Additions in Rel-6: Not Present + L... .... = Additions in Rel-7: 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_dl_tbf[] = { + 0x2d, 0x06, 0x3f, 0x30, 0x0f, 0xe3, 0x67, 0x7d, 0x80, 0x00, + 0x1c, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03, + 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); @@ -162,6 +221,12 @@ rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_tbf_nr, rlcmac_prim->l1ctl.cfg_ul_tbf_req.ul_slotmask); break; + case OSMO_PRIM(OSMO_GPRS_RLCMAC_L1CTL_CFG_DL_TBF, PRIM_OP_REQUEST): + printf("%s(): Rx %s dl_tbf_nr=%u dl_slotmask=0x%02x dl_tfi=%u\n", __func__, pdu_name, + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tbf_nr, + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_slotmask, + rlcmac_prim->l1ctl.cfg_dl_tbf_req.dl_tfi); + break; default: printf("%s(): Rx %s\n", __func__, pdu_name); } @@ -173,6 +238,37 @@ return 0; }
+static const uint8_t llc_dummy_command[] = { + 0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b +}; + +static struct msgb *create_dl_data_block(uint8_t dl_tfi, uint8_t usf, enum gprs_rlcmac_coding_scheme cs, uint8_t bsn, bool fbi) +{ + struct msgb *msg = msgb_alloc(128, __func__); + struct gprs_rlcmac_rlc_dl_data_header *hdr; + struct gprs_rlcmac_rlc_li_field *lime; + + hdr = (struct gprs_rlcmac_rlc_dl_data_header *)msgb_put(msg, gprs_rlcmac_mcs_size_dl(cs)); + hdr->pt = 0; /* RLC/MAC block contains an RLC data block */ + hdr->rrbp = 0; + hdr->s_p = 0; + hdr->usf = usf; + hdr->pr = 0; + hdr->tfi = dl_tfi; + hdr->fbi = fbi ? 1 : 0; + hdr->tfi = dl_tfi; + hdr->bsn = bsn; + hdr->e = 0; + lime = &hdr->lime[0]; + lime->li = sizeof(llc_dummy_command); + lime->m = 0; + lime->e = 1; + msg->l3h = &lime->ll_pdu[0]; + memset(msg->l3h, 0x2b, msgb_l3len(msg)); + memcpy(msg->l3h, llc_dummy_command, sizeof(llc_dummy_command)); + return msg; +} + void prepare_test(void) { int rc; @@ -183,6 +279,12 @@ osmo_gprs_rlcmac_prim_set_down_cb(test_rlcmac_prim_down_cb, NULL); }
+void cleanup_test(void) +{ + /* Reinit the RLCMAC layer so that data generated during the test is freed within the test context: */ + osmo_gprs_rlcmac_init(OSMO_GPRS_RLCMAC_LOCATION_MS); +} + static void test_ul_tbf_attach(void) { struct osmo_gprs_rlcmac_prim *rlcmac_prim; @@ -210,7 +312,46 @@ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
OSMO_ASSERT(rc == 0); + printf("=== %s end ===\n", __func__); + cleanup_test(); +} + +/* PCU allocates a DL TBF through PCH ImmAss for MS (when in packet-idle) */ +static void test_dl_tbf_ccch_assign(void) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + int rc; + struct msgb *dl_data_msg; + + printf("=== %s start ===\n", __func__); + prepare_test(); + uint32_t tlli = 0x0000001; + uint8_t ts_nr = 7; + uint8_t usf = 0; + uint32_t rts_fn = 4; + uint8_t dl_tfi = 0; + + /* Notify RLCMAC about our TLLI */ + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_gmmrr_assign_req(tlli); + rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim); + + OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_dl_tbf) == GSM_MACBLOCK_LEN); + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_dl_tbf); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* Transmit some DL LLC data MS<-PCU */ + dl_data_msg = create_dl_data_block(dl_tfi, usf, GPRS_RLCMAC_CS_1, 0, 1); + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_data_ind(ts_nr, rts_fn, 0, 0, 0, + msgb_data(dl_data_msg), + msgb_length(dl_data_msg)); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + msgb_free(dl_data_msg); + + printf("=== %s end ===\n", __func__); + cleanup_test(); }
static const struct log_info_cat test_log_categories[] = { }; @@ -234,6 +375,7 @@ log_set_use_color(osmo_stderr_target, 0);
test_ul_tbf_attach(); + test_dl_tbf_ccch_assign();
talloc_free(tall_ctx); } diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err index e6d6b30..89a970c 100644 --- a/tests/rlcmac/rlcmac_prim_test.err +++ b/tests/rlcmac/rlcmac_prim_test.err @@ -25,3 +25,15 @@ DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying 1 RLC blocks, 1 BSNs DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying data unit 0 (BSN 0) DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) msg block (BSN 0, CS-2): 3c 00 01 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 11 e5 10 00 00 +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated +DLGLOBAL INFO UL_TBF{FLOW}: Deallocated +DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request +DLGLOBAL INFO GMMRR-ASSIGN.req: creating new entity TLLI=0x00000001 +DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication +DLGLOBAL INFO GRE(00000001) Got PCH IMM_ASS (DL_TBF): DL_TFI=0 TS=7 +DLGLOBAL INFO DL_TBF{NEW}: Allocated +DLGLOBAL INFO DL_TBF{NEW}: Received Event DL_ASS_COMPL +DLGLOBAL INFO TBF(DL:NR-0:TLLI-00000001) Send L1CTL-CF_DL_TBF.req dl_slotmask=0x80 dl_tfi=0 +DLGLOBAL INFO DL_TBF{NEW}: state_chg to FLOW +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Rx new DL data diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok index 6e0db40..808ce21 100644 --- a/tests/rlcmac/rlcmac_prim_test.ok +++ b/tests/rlcmac/rlcmac_prim_test.ok @@ -3,3 +3,6 @@ test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80 test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[3c 00 01 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 11 e5 10 00 00 ] === test_ul_tbf_attach end === +=== test_dl_tbf_ccch_assign start === +test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=0x80 dl_tfi=0 +=== test_dl_tbf_ccch_assign end ===