pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/31576 )
Change subject: rlcmac: dl_tbf: Improve logic requesting a new UL TBF ...................................................................... rlcmac: dl_tbf: Improve logic requesting a new UL TBF Change-Id: I702872ba32a410bb5f09943af3cdadca482562db --- M include/osmocom/gprs/rlcmac/gre.h M include/osmocom/gprs/rlcmac/tbf_ul.h M include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h M src/rlcmac/gre.c M src/rlcmac/rlcmac.c M src/rlcmac/rlcmac_enc.c M src/rlcmac/sched.c M src/rlcmac/tbf_ul.c M src/rlcmac/tbf_ul_ass_fsm.c M tests/rlcmac/rlcmac_prim_test.c M tests/rlcmac/rlcmac_prim_test.err M tests/rlcmac/rlcmac_prim_test.ok 12 files changed, 500 insertions(+), 26 deletions(-) Approvals: pespin: Looks good to me, approved Jenkins Builder: Verified diff --git a/include/osmocom/gprs/rlcmac/gre.h b/include/osmocom/gprs/rlcmac/gre.h index ca5f773..f6397a6 100644 --- a/include/osmocom/gprs/rlcmac/gre.h +++ b/include/osmocom/gprs/rlcmac/gre.h @@ -20,6 +20,10 @@ struct gprs_rlcmac_entity *gprs_rlcmac_entity_alloc(uint32_t tlli); void gprs_rlcmac_entity_free(struct gprs_rlcmac_entity *gre); +bool gprs_rlcmac_entity_in_packet_idle_mode(const struct gprs_rlcmac_entity *gre); +bool gprs_rlcmac_entity_in_packet_transfer_mode(const struct gprs_rlcmac_entity *gre); +bool gprs_rlcmac_entity_have_tx_data_queued(const struct gprs_rlcmac_entity *gre); + int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_pdu, unsigned int ll_pdu_len, enum osmo_gprs_rlcmac_llc_sapi sapi, uint8_t radio_prio); diff --git a/include/osmocom/gprs/rlcmac/tbf_ul.h b/include/osmocom/gprs/rlcmac/tbf_ul.h index 3382778..ab85f50 100644 --- a/include/osmocom/gprs/rlcmac/tbf_ul.h +++ b/include/osmocom/gprs/rlcmac/tbf_ul.h @@ -58,6 +58,9 @@ int gprs_rlcmac_ul_tbf_handle_pkt_ul_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf, const RlcMacDownlink_t *dl_block); +int gprs_rlcmac_ul_tbf_handle_pkt_ul_ass(struct gprs_rlcmac_ul_tbf *ul_tbf, + const struct osmo_gprs_rlcmac_prim *rlcmac_prim, + const RlcMacDownlink_t *dl_block); static inline struct gprs_rlcmac_tbf *ul_tbf_as_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf) { diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h index 4a1658d..377c86c 100644 --- a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h +++ b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h @@ -32,14 +32,11 @@ struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_ul_tbf *ul_tbf; }; + const struct gprs_rlcmac_dl_tbf *dl_tbf; /* Not null if assignment was started by a DL TBF ACK/NACK */ enum gprs_rlcmac_tbf_ul_ass_type ass_type; uint8_t rach_req_ra; struct gprs_rlcmac_ul_tbf_allocation phase1_alloc; struct gprs_rlcmac_ul_tbf_allocation phase2_alloc; - struct { /* Filled when we receive the poll; exact time here the response PKT CTL ACK is to be transmitted: */ - uint8_t ts; - uint32_t fn; - } sched_pkt_ctrl_ack; /* Number of packet resource request transmitted (T3168) */ unsigned int pkt_res_req_proc_attempts; }; @@ -47,9 +44,10 @@ enum tbf_ul_ass_fsm_event { GPRS_RLCMAC_TBF_UL_ASS_EV_START, /* Start Uplink assignment (data: enum gprs_rlcmac_tbf_ul_ass_type) */ GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, /* Start Uplink assignment directly into 2phase from an older UL TBF */ + GPRS_RLCMAC_TBF_UL_ASS_EV_START_FROM_DL_TBF, /* Uplink assignment requested by DL TBF ACK/NACK, wait to receive Pkt Ul Ass on its PACCH */ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, /* (data: struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx *) */ GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, /* Generate RLC/MAC block (data: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */ - GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, /* (data: decoded PktUlAss) */ + GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, /* (data: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */ GPRS_RLCMAC_TBF_UL_ASS_EV_FOOBAR, }; @@ -59,6 +57,12 @@ const IA_RestOctets_t *iaro; }; +struct tbf_ul_ass_ev_rx_pkt_ul_ass_ctx { + uint8_t ts_nr; + uint32_t fn; + const RlcMacDownlink_t *dl_block; /* decoded PktUlAss */ +}; + struct tbf_ul_ass_ev_create_rlcmac_msg_ctx { uint8_t ts; /* TS where the created UL ctrl block is to be sent */ uint32_t fn; /* FN where the created UL ctrl block is to be sent */ @@ -73,6 +77,8 @@ int gprs_rlcmac_tbf_ul_ass_start(struct gprs_rlcmac_ul_tbf *ul_tbf, enum gprs_rlcmac_tbf_ul_ass_type type); int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf, struct gprs_rlcmac_ul_tbf *old_ul_tbf); +int gprs_rlcmac_tbf_ul_ass_start_from_dl_tbf_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_dl_tbf *dl_tbf); + bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf); bool gprs_rlcmac_tbf_ul_ass_match_rach_req(struct gprs_rlcmac_ul_tbf *ul_tbf, uint8_t ra); bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi); diff --git a/src/rlcmac/gre.c b/src/rlcmac/gre.c index 40cd585..53d53c7 100644 --- a/src/rlcmac/gre.c +++ b/src/rlcmac/gre.c @@ -66,6 +66,40 @@ talloc_free(gre); } +/* TS 44.060 5.3 In packet idle mode: +* - no temporary block flow (TBF) exists.. +* - the mobile station monitors the relevant paging subchannels on CCCH. In packet +* idle mode, upper layers may require the transfer of a upper layer PDU, which +* implicitly triggers the establishment of a TBF and the transition to packet +* transfer mode. In packet idle mode, upper layers may require the establishment +* of an RR connection. When the mobile station enters dedicated mode (see 3GPP TS +* 44.018), it may leave the packet idle mode, if the mobile station limitations +* make it unable to handle the RR connection and the procedures in packet idle +* mode simultaneously.*/ +bool gprs_rlcmac_entity_in_packet_idle_mode(const struct gprs_rlcmac_entity *gre) +{ + return !gre->ul_tbf && !gre->dl_tbf; +} + +/* TS 44.060 5.4 "In packet transfer mode, the mobile station is allocated radio +* resources providing one or more TBFs. [...] +* When a transfer of upper layer PDUs +* terminates, in either downlink or uplink direction, the corresponding TBF is +* released. In packet transfer mode, when all TBFs have been released, in downlink +* and uplink direction, the mobile station returns to packet idle mode." +*/ +bool gprs_rlcmac_entity_in_packet_transfer_mode(const struct gprs_rlcmac_entity *gre) +{ + return gre->ul_tbf || gre->dl_tbf; +} + +/* Whether MS has data queued from upper layers waiting to be transmitted in the + * Tx queue (an active UL TBF may still have some extra data) */ +bool gprs_rlcmac_entity_have_tx_data_queued(const struct gprs_rlcmac_entity *gre) +{ + return gprs_rlcmac_llc_queue_size(gre->llc_queue) > 0; +} + int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_pdu, unsigned int ll_pdu_len, enum osmo_gprs_rlcmac_llc_sapi sapi, uint8_t radio_prio) { @@ -75,7 +109,11 @@ if (rc < 0) return rc; - if (!gre->ul_tbf) { + /* TS 44.060 5.3 "In packet idle mode, upper layers may require the + * transfer of a upper layer PDU, which implicitly triggers the + * establishment of a TBF and the transition to packet transfer mode." */ + if (gprs_rlcmac_entity_in_packet_idle_mode(gre)) { + OSMO_ASSERT(!gre->ul_tbf); /* We have new data in the queue but we have no ul_tbf. Allocate one and start UL Assignment. */ gre->ul_tbf = gprs_rlcmac_ul_tbf_alloc(gre); if (!gre->ul_tbf) diff --git a/src/rlcmac/rlcmac.c b/src/rlcmac/rlcmac.c index 4023586..82394e6 100644 --- a/src/rlcmac/rlcmac.c +++ b/src/rlcmac/rlcmac.c @@ -358,6 +358,58 @@ return rc; } +static int gprs_rlcmac_handle_pkt_ul_ass(const struct osmo_gprs_rlcmac_prim *rlcmac_prim, const RlcMacDownlink_t *dl_block) +{ + struct gprs_rlcmac_entity *gre = NULL; + struct gprs_rlcmac_ul_tbf *ul_tbf = NULL; + struct gprs_rlcmac_dl_tbf *dl_tbf; + const Packet_Uplink_Assignment_t *ulass = &dl_block->u.Packet_Uplink_Assignment; + int rc; + + /* Attempt to find relevant UL TBF in assignment state from ID (set "gre" ptr): */ + switch (ulass->ID.UnionType) { + case 0: /* GLOBAL_TFI: */ + switch (ulass->ID.u.Global_TFI.UnionType) { + case 0: /* UL TFI */ + ul_tbf = gprs_rlcmac_find_ul_tbf_by_tfi(ulass->ID.u.Global_TFI.u.UPLINK_TFI); + gre = ul_tbf->tbf.gre; + break; + case 1: /* DL TFI */ + dl_tbf = gprs_rlcmac_find_dl_tbf_by_tfi(ulass->ID.u.Global_TFI.u.DOWNLINK_TFI); + if (dl_tbf) + gre = dl_tbf->tbf.gre; + break; + default: + OSMO_ASSERT(0); + } + break; + case 1: /* TLLI */ + gre = gprs_rlcmac_find_entity_by_tlli(ulass->ID.u.TLLI); + if (gre) + ul_tbf = gre->ul_tbf; + break; + case 2: /* TQI */ + case 3: /* Packet_Request_Reference */ + LOGRLCMAC(LOGL_NOTICE, "TS=%u FN=%u Rx Pkt UL ASS: HANDLING OF ID=%u NOT IMPLEMENTED!\n", + ulass->ID.UnionType, + rlcmac_prim->l1ctl.pdch_data_ind.ts_nr, + rlcmac_prim->l1ctl.pdch_data_ind.fn); + break; + } + + if (!gre->ul_tbf) { + LOGRLCMAC(LOGL_INFO, "TS=%u FN=%u Rx Pkt UL ACK/NACK: UL_TBF TFI=%u not found\n", + rlcmac_prim->l1ctl.pdch_data_ind.ts_nr, + rlcmac_prim->l1ctl.pdch_data_ind.fn, + dl_block->TFI); + return -ENOENT; + } + + rc = gprs_rlcmac_ul_tbf_handle_pkt_ul_ass(gre->ul_tbf, rlcmac_prim, dl_block); + + return rc; +} + static int gprs_rlcmac_handle_gprs_dl_ctrl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim) { struct bitvec *bv; @@ -388,6 +440,9 @@ case OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ACK_NACK: rc = gprs_rlcmac_handle_pkt_ul_ack_nack(rlcmac_prim, dl_ctrl_block); break; + case OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ASSIGNMENT: + rc = gprs_rlcmac_handle_pkt_ul_ass(rlcmac_prim, dl_ctrl_block); + break; default: LOGRLCMAC(LOGL_ERROR, "TS=%u FN=%u Rx %s NOT SUPPORTED! ignoring\n", rlcmac_prim->l1ctl.pdch_data_ind.ts_nr, diff --git a/src/rlcmac/rlcmac_enc.c b/src/rlcmac/rlcmac_enc.c index 6bceb8d..ef1d4cd 100644 --- a/src/rlcmac/rlcmac_enc.c +++ b/src/rlcmac/rlcmac_enc.c @@ -386,6 +386,7 @@ { Packet_Downlink_Ack_Nack_t *ack = &block->u.Packet_Downlink_Ack_Nack; struct gprs_rlcmac_entity *gre = dl_tbf->tbf.gre; + int rc; memset(block, 0, sizeof(*block)); ack->MESSAGE_TYPE = OSMO_GPRS_RLCMAC_UL_MSGT_PACKET_RESOURCE_REQUEST; @@ -395,8 +396,9 @@ ack->DOWNLINK_TFI = dl_tbf->cur_alloc.dl_tfi; gprs_rlcmac_enc_prepare_pkt_ack_nack_desc_gprs(&ack->Ack_Nack_Description, dl_tbf); - /* Channel Request Description */ - if (gre->ul_tbf && gprs_rlcmac_tbf_ul_ass_pending(gre->ul_tbf)) { + /* Channel Request Description. Request a UL-TBF if we have UL data + * queued to send and no active UL BF (TS 44.060 8.1.2.5) */ + if (!gre->ul_tbf && gprs_rlcmac_entity_have_tx_data_queued(gre)) { Channel_Request_Description_t *chan_req = &ack->Channel_Request_Description; ack->Exist_Channel_Request_Description = 1; chan_req->PEAK_THROUGHPUT_CLASS = 0; /* TODO */ @@ -404,6 +406,11 @@ chan_req->RLC_MODE = GPRS_RLCMAC_RLC_MODE_ACKNOWLEDGED; chan_req->LLC_PDU_TYPE = GPRS_RLCMAC_LLC_PDU_TYPE_ACKNOWLEDGED; chan_req->RLC_OCTET_COUNT = 0; /* TODO */ + + gre->ul_tbf = gprs_rlcmac_ul_tbf_alloc(gre); + rc = gprs_rlcmac_tbf_ul_ass_start_from_dl_tbf_ack_nack(gre->ul_tbf, dl_tbf); + if (rc < 0) + LOGPTBFDL(dl_tbf, LOGL_ERROR, "Failed starting assignment of requested UL TBF (%d)\n", rc); } else { ack->Exist_Channel_Request_Description = 0; } diff --git a/src/rlcmac/sched.c b/src/rlcmac/sched.c index c2b981f..6ec76c7 100644 --- a/src/rlcmac/sched.c +++ b/src/rlcmac/sched.c @@ -37,7 +37,8 @@ struct gprs_rlcmac_dl_tbf *poll_dl_ack; /* 8.1.2.2 7) */ struct gprs_rlcmac_ul_tbf *poll_ul_ack_new_ul_tbf; /* 9.3.2.4.2 (answer with PKT RES REQ) */ struct gprs_rlcmac_ul_tbf *poll_ul_ack; /* 11.2.2 (answer with PKT CTRL ACK) */ - struct gprs_rlcmac_ul_tbf *ul_ass; + struct gprs_rlcmac_ul_tbf *poll_ul_ass; /* (answer Pkt UL ASS with PKT CTRL ACK) */ + struct gprs_rlcmac_ul_tbf *ul_ass; /* PCU grants USF/SBA: transmit Pkt Res Req (2phase access)*/ }; static inline bool fn_valid(uint32_t fn) @@ -80,7 +81,8 @@ if (node) { switch (node->reason) { case GPRS_RLCMAC_PDCH_ULC_POLL_UL_ASS: - /* TODO */ + /* Answer with ctrl ack generated by ul_tbf->ul_ass_fsm. */ + tbfs->poll_ul_ass = tbf_as_ul_tbf(node->tbf); break; case GPRS_RLCMAC_PDCH_ULC_POLL_DL_ASS: /* TODO */ @@ -207,6 +209,11 @@ gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack); return msg; } + if (tbfs->poll_ul_ass) { + msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(tbfs->poll_ul_ass, bi); + if (msg) + return msg; + } if (tbfs->ul_ass) { msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, bi); if (msg) diff --git a/src/rlcmac/tbf_ul.c b/src/rlcmac/tbf_ul.c index 7642832..fcd7f56 100644 --- a/src/rlcmac/tbf_ul.c +++ b/src/rlcmac/tbf_ul.c @@ -261,6 +261,21 @@ return rc; } +int gprs_rlcmac_ul_tbf_handle_pkt_ul_ass(struct gprs_rlcmac_ul_tbf *ul_tbf, + const struct osmo_gprs_rlcmac_prim *rlcmac_prim, + const RlcMacDownlink_t *dl_block) +{ + int rc; + struct tbf_ul_ass_ev_rx_pkt_ul_ass_ctx d = { + .ts_nr = rlcmac_prim->l1ctl.pdch_data_ind.ts_nr, + .fn = rlcmac_prim->l1ctl.pdch_data_ind.fn, + .dl_block = dl_block, + }; + + rc = osmo_fsm_inst_dispatch(ul_tbf->ul_ass_fsm.fi, GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, &d); + return rc; +} + struct msgb *gprs_rlcmac_ul_tbf_dummy_create(const struct gprs_rlcmac_ul_tbf *ul_tbf) { struct msgb *msg; @@ -333,7 +348,7 @@ bool gprs_rlcmac_ul_tbf_have_data(const struct gprs_rlcmac_ul_tbf *ul_tbf) { return (ul_tbf->llc_tx_msg && msgb_length(ul_tbf->llc_tx_msg) > 0) || - (gprs_rlcmac_llc_queue_size(ul_tbf->tbf.gre->llc_queue) > 0); + gprs_rlcmac_entity_have_tx_data_queued(ul_tbf->tbf.gre); } bool gprs_rlcmac_ul_tbf_shall_keep_open(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi) diff --git a/src/rlcmac/tbf_ul_ass_fsm.c b/src/rlcmac/tbf_ul_ass_fsm.c index 6169080..d88acd3 100644 --- a/src/rlcmac/tbf_ul_ass_fsm.c +++ b/src/rlcmac/tbf_ul_ass_fsm.c @@ -32,12 +32,14 @@ #include <osmocom/gprs/rlcmac/sched.h> #include <osmocom/gprs/rlcmac/csn1_defs.h> #include <osmocom/gprs/rlcmac/rlcmac_enc.h> +#include <osmocom/gprs/rlcmac/pdch_ul_controller.h> #define X(s) (1 << (s)) static const struct value_string tbf_ul_ass_fsm_event_names[] = { { GPRS_RLCMAC_TBF_UL_ASS_EV_START, "START" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, "START_DIRECT_2PHASE" }, + { GPRS_RLCMAC_TBF_UL_ASS_EV_START_FROM_DL_TBF, "START_FROM_DL_TBF" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, "RX_CCCH_IMM_ASS" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, "RX_PKT_UL_ASS" }, @@ -165,14 +167,73 @@ return -EFAULT; } +static int handle_pkt_ul_ass(struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx, const struct tbf_ul_ass_ev_rx_pkt_ul_ass_ctx *d) +{ + + const Packet_Uplink_Assignment_t *ulass = &d->dl_block->u.Packet_Uplink_Assignment; + uint8_t tn; + const Timeslot_Allocation_t *ts_alloc; + const Timeslot_Allocation_Power_Ctrl_Param_t *ts_alloc_pwr_ctl; + + switch (ulass->UnionType) { + case 0: /* ulass->u.PUA_GPRS_Struct.* (PUA_GPRS_t) */ + ctx->ul_tbf->tx_cs = ulass->u.PUA_GPRS_Struct.CHANNEL_CODING_COMMAND + 1; + switch (ulass->u.PUA_GPRS_Struct.UnionType) { + case 1: /* Dynamic Allocation (Dynamic_Allocation_t) */ + if (ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.Exist_UPLINK_TFI_ASSIGNMENT) + ctx->phase2_alloc.ul_tfi = ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.UPLINK_TFI_ASSIGNMENT; + /* TODO: P0, PR_MODE, USF_GRANULARITY, RLC_DATA_BLOCKS_GRANTED, TBF_Starting_Time */ + switch (ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.UnionType) { + case 0: /* Timeslot_Allocation_t */ + ts_alloc = &ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.u.Timeslot_Allocation[0]; + ctx->phase2_alloc.num_ts = 0; + for (tn = 0; tn < 8; tn++) { + ctx->phase2_alloc.ts[tn].allocated = ts_alloc[tn].Exist; + if (ts_alloc[tn].Exist) { + ctx->phase2_alloc.num_ts++; + ctx->phase2_alloc.ts[tn].usf = ts_alloc[tn].USF_TN; + } + } + break; + case 1: /* Timeslot_Allocation_Power_Ctrl_Param_t */ + /* TODO: ALPHA, GAMMA */ + ts_alloc_pwr_ctl = &ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.u.Timeslot_Allocation_Power_Ctrl_Param; + ctx->phase2_alloc.num_ts = 0; + for (tn = 0; tn < 8; tn++) { + ctx->phase2_alloc.ts[tn].allocated = ts_alloc_pwr_ctl->Slot[tn].Exist; + if (ts_alloc_pwr_ctl->Slot[tn].Exist) { + ctx->phase2_alloc.num_ts++; + ctx->phase2_alloc.ts[tn].usf = ts_alloc_pwr_ctl->Slot[tn].USF_TN; + } + } + break; + } + break; + case 2: /* Single Block Allocation */ + LOGPFSML(ctx->fi, LOGL_NOTICE, "Rx Pkt Ul Ass GPRS Single Block Allocation not supported!\n"); + return -ENOTSUP; + case 0: /* Fixed Allocation */ + LOGPFSML(ctx->fi, LOGL_NOTICE, "Rx Pkt Ul Ass GPRS Fixed Allocation not supported!\n"); + return -ENOTSUP; + } + return 0; + case 1: /* ulass->u.PUA_EGPRS_Struct.* (PUA_EGPRS_t) */ + LOGPFSML(ctx->fi, LOGL_NOTICE, "Rx Pkt Ul Ass EGPRS not supported!\n"); + return -ENOTSUP; + } + + OSMO_ASSERT(0); + return -EFAULT; +} + static void st_idle_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) { struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; /* Reset state: */ + ctx->dl_tbf = NULL; memset(&ctx->phase1_alloc, 0, sizeof(ctx->phase1_alloc)); memset(&ctx->phase2_alloc, 0, sizeof(ctx->phase2_alloc)); - memset(&ctx->sched_pkt_ctrl_ack, 0, sizeof(ctx->sched_pkt_ctrl_ack)); } static void st_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data) @@ -191,6 +252,11 @@ ctx->ass_type = GPRS_RLCMAC_TBF_UL_ASS_TYPE_2PHASE; tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ); break; + case GPRS_RLCMAC_TBF_UL_ASS_EV_START_FROM_DL_TBF: + osmo_fsm_inst_dispatch(ctx->ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_UL_ASS_START, NULL); + ctx->ass_type = GPRS_RLCMAC_TBF_UL_ASS_TYPE_2PHASE; + tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS); + break; default: OSMO_ASSERT(0); } @@ -235,12 +301,27 @@ static void st_wait_pkt_ul_ass(struct osmo_fsm_inst *fi, uint32_t event, void *data) { - //struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; + struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; + struct tbf_ul_ass_ev_rx_pkt_ul_ass_ctx *d; + int rc; + switch (event) { case GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS: - // TODO: fill ctx->phase2_alloc with contents from pkt_ul_ass + d = data; + rc = handle_pkt_ul_ass(ctx, d); + if (rc < 0) + LOGPFSML(fi, LOGL_ERROR, "Rx Pkt Ul Ass: failed to parse!\n"); // TODO: what to do if Pkt_ul_ass is "reject"? need to check spec, depending on cause. - tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK); + /* If RRBP contains valid data, schedule a response (PKT CONTROL ACK or PKT RESOURCE REQ). */ + if (d->dl_block->SP) { + uint32_t poll_fn = rrbp2fn(d->fn, d->dl_block->RRBP); + gprs_rlcmac_pdch_ulc_reserve(g_ctx->sched.ulc[d->ts_nr], poll_fn, + GPRS_RLCMAC_PDCH_ULC_POLL_UL_ASS, + ul_tbf_as_tbf(ctx->ul_tbf)); + tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK); + } else { + tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL); + } break; default: OSMO_ASSERT(0); @@ -249,15 +330,13 @@ static void st_sched_pkt_ctrl_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data) { - //struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; + struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; struct tbf_ul_ass_ev_create_rlcmac_msg_ctx *data_ctx; switch (event) { case GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG: data_ctx = (struct tbf_ul_ass_ev_create_rlcmac_msg_ctx *)data; - LOGPFSML(fi, LOGL_ERROR, "TODO: create PKT CTRL ACK...\n"); - //data_ctx->msg = create_packet_ctrl_ack(ctx, data_ctx); - data_ctx->msg = NULL; + data_ctx->msg = gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(ctx->ul_tbf); if (!data_ctx->msg) return; tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL); @@ -275,7 +354,7 @@ if (ctx->ass_type == GPRS_RLCMAC_TBF_UL_ASS_TYPE_1PHASE) memcpy(&ctx->ul_tbf->cur_alloc, &ctx->phase1_alloc, sizeof(ctx->phase1_alloc)); else - memcpy(&ctx->ul_tbf->cur_alloc, &ctx->phase2_alloc, sizeof(ctx->phase1_alloc)); + memcpy(&ctx->ul_tbf->cur_alloc, &ctx->phase2_alloc, sizeof(ctx->phase2_alloc)); /* Inform the main TBF state about the assignment completed: */ osmo_fsm_inst_dispatch(ctx->ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_UL_ASS_COMPL, NULL); /* Go back to IDLE state. */ @@ -286,10 +365,12 @@ [GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE] = { .in_event_mask = X(GPRS_RLCMAC_TBF_UL_ASS_EV_START) | - X(GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE), + X(GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE) | + X(GPRS_RLCMAC_TBF_UL_ASS_EV_START_FROM_DL_TBF), .out_state_mask = X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS) | - X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ), + X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ) | + X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS), .name = "IDLE", .onenter = st_idle_on_enter, .action = st_idle, @@ -316,7 +397,8 @@ X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS), .out_state_mask = X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ) | - X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK), + X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK) | + X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL), .name = "WAIT_PKT_UL_ASS", .action = st_wait_pkt_ul_ass, }, @@ -343,6 +425,17 @@ struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *)fi->priv; switch (fi->T) { case 3168: + /* If the UL TBF assignment was started from DL TBF it is not + really possible reattempting because we haven't yet any phase1 + allocation. Hence simply destroy the TBF and let next DL TBF DL + ACK/NACK re-request an UL TBF assignment: */ + if (ctx->dl_tbf) { + LOGPFSML(ctx->fi, LOGL_NOTICE, + "UL TBF establishment failure (T3168 timeout attempts=%u, ass from DL TBF)\n", + ctx->pkt_res_req_proc_attempts); + gprs_rlcmac_ul_tbf_free(ctx->ul_tbf); + return 0; + } /* TS 44.060 7.1.3.3: "the mobile station shall then reinitiate the packet access * procedure unless the packet access procedure has already been attempted four * times. In that case, TBF failure has occurred and an RLC/MAC error should be @@ -424,6 +517,18 @@ return rc; } +/* A DL-TBF requested a UL TBF over DL ACK/NACK, wait to receive Pkt Ul Ass for + * it, aka switch the FSM to trigger the 2hpase directly (tx Pkt Res Req) */ +int gprs_rlcmac_tbf_ul_ass_start_from_dl_tbf_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_dl_tbf *dl_tbf) +{ + int rc; + ul_tbf->ul_ass_fsm.dl_tbf = dl_tbf; + rc = osmo_fsm_inst_dispatch(ul_tbf->ul_ass_fsm.fi, + GPRS_RLCMAC_TBF_UL_ASS_EV_START_FROM_DL_TBF, + NULL); + return rc; +} + bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf) { return ul_tbf->ul_ass_fsm.fi->state != GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE; @@ -449,9 +554,6 @@ case GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ: return (ctx->phase1_alloc.ts[bi->ts].allocated && ctx->phase1_alloc.ts[bi->ts].usf == bi->usf); - case GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK: - return (ctx->sched_pkt_ctrl_ack.ts == bi->ts && - ctx->sched_pkt_ctrl_ack.fn == bi->fn); default: return false; }; diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c index 02ee04c..604546d 100644 --- a/tests/rlcmac/rlcmac_prim_test.c +++ b/tests/rlcmac/rlcmac_prim_test.c @@ -295,6 +295,75 @@ ack_desc->RECEIVED_BLOCK_BITMAP[sizeof(ack_desc->RECEIVED_BLOCK_BITMAP) - idx/8 - 1] &= ~(1 << (idx & 0x03)); } +static void pkt_ul_ass_from_dl_tbf_init(RlcMacDownlink_t *block, uint8_t dl_tfi, uint8_t new_ul_tfi, uint16_t arfcn, uint8_t *usf_li) +{ + Packet_Uplink_Assignment_t *pua = &block->u.Packet_Uplink_Assignment; + PUA_GPRS_t *gprs = &pua->u.PUA_GPRS_Struct; + Packet_Timing_Advance_t *pta = &gprs->Packet_Timing_Advance; + Frequency_Parameters_t *fp = &gprs->Frequency_Parameters; + Dynamic_Allocation_t *da = &gprs->u.Dynamic_Allocation; + unsigned int tn; + + memset(block, 0, sizeof(*block)); + block->PAYLOAD_TYPE = GPRS_RLCMAC_PT_CONTROL_BLOCK; + block->RRBP = 0; + block->SP = 0; + block->USF = 0x00; + block->u.MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ASSIGNMENT; + + /* See 3GPP TS 44.060, section 11.2.29 */ + pua = &block->u.Packet_Uplink_Assignment; + pua->MESSAGE_TYPE = OSMO_GPRS_RLCMAC_DL_MSGT_PACKET_UPLINK_ASSIGNMENT; + pua->PAGE_MODE = 0x00; + + /* TLLI or Global DL TFI */ + pua->ID.UnionType = 0x00; + pua->ID.u.Global_TFI.UnionType = 0x01; + pua->ID.u.Global_TFI.u.UPLINK_TFI = dl_tfi; + + /* GPRS specific parameters */ + pua->UnionType = 0x00; + /* Use the commanded CS/MCS value during the content resolution */ + gprs->CHANNEL_CODING_COMMAND = gprs_rlcmac_mcs_chan_code(GPRS_RLCMAC_MCS_2); + gprs->TLLI_BLOCK_CHANNEL_CODING = 0x01; // ^^^ + /* Dynamic allocation */ + gprs->UnionType = 0x01; + /* Frequency Parameters IE is present */ + gprs->Exist_Frequency_Parameters = 0x01; + + /* Packet Timing Advance (if known) */ + pta->Exist_TIMING_ADVANCE_VALUE = 0x01; // Present + pta->TIMING_ADVANCE_VALUE = 1; + + /* Continuous Timing Advance Control */ + pta->Exist_IndexAndtimeSlot = 0x01; // Present + pta->TIMING_ADVANCE_TIMESLOT_NUMBER = 0; // FIXME! + pta->TIMING_ADVANCE_INDEX = 2; + + /* Frequency Parameters IE */ + fp->TSC = 2; + fp->UnionType = 0x00; + fp->u.ARFCN = arfcn; + + /* Dynamic allocation parameters */ + da->USF_GRANULARITY = 0x00; + + /* Assign an Uplink TFI */ + da->Exist_UPLINK_TFI_ASSIGNMENT = 0x01; + da->UPLINK_TFI_ASSIGNMENT = new_ul_tfi; + + /* Timeslot Allocation with or without Power Control */ + da->UnionType = 0x00; + + for (tn = 0; tn < 8; tn++) { + Timeslot_Allocation_t *slot = &da->u.Timeslot_Allocation[tn]; + if (usf_li[tn] == 0xff) + continue; + slot->Exist = 0x01; // Enable this timeslot + slot->USF_TN = usf_li[tn]; // USF_TN(i) + } +} + static uint8_t *create_si13(uint8_t bs_cv_max /* 0..15 */) { static uint8_t si13_buf[GSM_MACBLOCK_LEN]; @@ -869,6 +938,88 @@ cleanup_test(); } +/* PCU allocates a DL TBF through PCH ImmAss for MS (when in packet-idle). Then + * upper layers want to transmit more data so during DL ACK/NACK a new UL TBF is + * requested. */ +static void test_dl_tbf_ccch_assign_requests_ul_tbf_pacch(void) +{ + struct osmo_gprs_rlcmac_prim *rlcmac_prim; + int rc; + struct msgb *dl_data_msg; + + printf("=== %s start ===\n", __func__); + prepare_test(); + RlcMacDownlink_t dl_block; + uint32_t tlli = 0x0000001; + uint8_t ts_nr = 7; + uint8_t usf = 0; + uint32_t rts_fn = 4; + uint8_t dl_tfi = 0; + uint8_t ul_tfi = 3; + uint8_t rrbp = GPRS_RLCMAC_RRBP_N_plus_17_18; + uint16_t arfcn = 871; + uint8_t usf_li[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 1, 2 }; + + /* 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, true, true, rrbp); + 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); + + /* Upper layers wants to transmit some payload, but no UL TBF exists yet: */ + /* Submit 14 bytes to fit in 1 RLCMAC block to shorten test and end up in FINISHED state quickly: */ + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req, 14); + rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM; + rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* Trigger transmission of DL ACK/NACK, which should request a UL TBF in "Channel Request Description" */ + rts_fn = rrbp2fn(rts_fn, rrbp); + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* Network sends a Pkt Ul Ass to DL TBF's PACCH: */ + rts_fn = fn_next_block(rts_fn); + pkt_ul_ass_from_dl_tbf_init(&dl_block, dl_tfi, ul_tfi, arfcn, &usf_li[0]); + /* has Poll set: */ + dl_block.SP = 1; + dl_block.RRBP = rrbp; + rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* Trigger transmission of PKT CTRL ACK */ + rts_fn = rrbp2fn(rts_fn, rrbp); + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf_li[ts_nr]); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + /* from now on use one of the assigned TS in UL TBF.*/ + rts_fn = fn_next_block(rts_fn); + ts_nr = 6; + + /* Trigger transmission of LLC data (GMM Attach) (first part) */ + rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf_li[ts_nr]); + rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim); + OSMO_ASSERT(rc == 0); + + printf("=== %s end ===\n", __func__); + cleanup_test(); +} + static const struct log_info_cat test_log_categories[] = { }; static const struct log_info test_log_info = { .cat = test_log_categories, @@ -899,6 +1050,7 @@ test_ul_tbf_last_data_cv0_retrans_max(); test_ul_tbf_request_another_ul_tbf(); test_dl_tbf_ccch_assign(); + test_dl_tbf_ccch_assign_requests_ul_tbf_pacch(); talloc_free(tall_ctx); } diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err index c022e4a..6ffd87d 100644 --- a/tests/rlcmac/rlcmac_prim_test.err +++ b/tests/rlcmac/rlcmac_prim_test.err @@ -620,3 +620,70 @@ DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx DL ACK/NACK FinalAck=1 DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) - V(N): "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR" R=Received I=Invalid DLGLOBAL INFO DL_TBF{FINISHED}: 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 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) DL DATA TFI=0 received (V(Q)=0 .. V(R)=0) +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Got CS-1 RLC data block: FBI=1, BSN=0, SPB=0, S/P=1 RRBP=1, E=0, bitoffs=24 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) BSN 0 storing in window (0..63) +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) data_length=20, data=19 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +DLGLOBAL DEBUG - Raising V(R) to 1 +DLGLOBAL DEBUG - Taking block 0 out, raising V(Q) to 1 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Assembling frames: (len=20) +DLGLOBAL DEBUG DL DATA LI contains extension octet: LI=6, M=0, E=1, count=0 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Frame 1 starts at offset 1, length=6, is_complete=1 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) complete UL frame len=6 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) No gaps in received block, last block: BSN=0 FBI=1 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) Finished with DL TBF +DLGLOBAL INFO DL_TBF{FLOW}: Received Event LAST_DL_DATA_RECVD +DLGLOBAL INFO DL_TBF{FLOW}: state_chg to FINISHED +DLGLOBAL DEBUG Register POLL (TS=7 FN=21, reason=DL_ACK) +DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication +DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx DL ACK/NACK FinalAck=1 +DLGLOBAL DEBUG TBF(DL:NR-0:TLLI-00000001) - V(N): "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIR" R=Received I=Invalid +DLGLOBAL INFO UL_TBF{NEW}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Allocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START_FROM_DL_TBF +DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START +DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN +DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to WAIT_PKT_UL_ASS +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication +DLGLOBAL INFO TS=7 FN=26 Rx Pkt UL ASS +DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: Received Event RX_PKT_UL_ASS +DLGLOBAL DEBUG Register POLL (TS=7 FN=43, reason=UL_ASS) +DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: state_chg to SCHED_PKT_CTRL_ACK +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication +DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_CTRL_ACK}: Received Event CREATE_RLCMAC_MSG +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Tx Packet Control Ack +DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_CTRL_ACK}: state_chg to COMPLETED +DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL +DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0xc0 +DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW +DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE +DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Sending new block at BSN 0, CS=CS-2 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Dequeue next LLC (len=14) +DLGLOBAL DEBUG -- Chunk with length 14 is less than remaining space (30): add length header to delimit LLC frame +DLGLOBAL DEBUG -- Final block, so we done. +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Complete UL frame, len=0 +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) data block (BSN 0, CS-2): 39 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) need_padding 0 spb_status 0 spb 0 (BSN1 0 BSN2 -1) +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Copying 1 RLC blocks, 1 BSNs +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Copying data unit 0 (BSN 0) +DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) msg block (BSN 0, CS-2): 00 06 00 39 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 +DLGLOBAL INFO UL_TBF{FLOW}: Received Event FIRST_UL_DATA_SENT +DLGLOBAL INFO UL_TBF{FLOW}: First UL block sent, stop T3164 +DLGLOBAL INFO UL_TBF{FLOW}: Received Event LAST_UL_DATA_SENT +DLGLOBAL INFO UL_TBF{FLOW}: Last UL block sent (CV=0), start T3182 +DLGLOBAL INFO UL_TBF{FLOW}: state_chg to FINISHED +DLGLOBAL INFO DL_TBF{FINISHED}: Deallocated +DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated +DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok index d2bce62..7bafb85 100644 --- a/tests/rlcmac/rlcmac_prim_test.ok +++ b/tests/rlcmac/rlcmac_prim_test.ok @@ -117,3 +117,12 @@ test_rlcmac_prim_up_cb(): Rx GRR-UNITDATA.indication TLLI=0x00000001 ll=[43 c0 01 2b 2b 2b ] test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=23 data=[40 14 00 00 00 00 00 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ] === test_dl_tbf_ccch_assign end === +=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch start === +sys={0.000000}, mono={0.000000}: clock_override_set +test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=0x80 dl_tfi=0 +test_rlcmac_prim_up_cb(): Rx GRR-UNITDATA.indication TLLI=0x00000001 ll=[43 c0 01 2b 2b 2b ] +test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=23 data=[40 14 00 00 00 00 00 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ] +test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0xc0 +test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=43 ts=7 data_len=23 data=[40 04 00 00 00 04 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ] +test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=47 ts=6 data_len=34 data=[00 06 00 39 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ] +=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch end === -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/31576 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: I702872ba32a410bb5f09943af3cdadca482562db Gerrit-Change-Number: 31576 Gerrit-PatchSet: 3 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <lafo...@osmocom.org> Gerrit-Reviewer: pespin <pes...@sysmocom.de> Gerrit-MessageType: merged