rlcmac: ul_tbf: Implement support for TBF Starting Time

While reworking tbf_ul_ass_fsm, avoid being in "ASSIGN" state while
waiting to send Pkt Ctrl Ack. The PCU is free to ask the TBF to transmit
data before receiving Pkt Ctrl Ack; the time where it can start
transmitting data is actually controlled by TBF Starting Time.

Change-Id: Id81f16743f2c464e01caf27ba2eb8c0fc715fe8a
This commit is contained in:
Pau Espin 2023-03-06 14:35:31 +01:00
parent ef3c599b98
commit 154ff41292
11 changed files with 225 additions and 53 deletions

View File

@ -46,3 +46,7 @@ void gprs_rlcmac_extract_rbb(const struct bitvec *rbb, char *show_rbb);
int gprs_rlcmac_decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc, int gprs_rlcmac_decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
struct bitvec *bits, int *bsn_begin, int *bsn_end, struct bitvec *bits, int *bsn_begin, int *bsn_end,
struct gprs_rlcmac_rlc_ul_window *ulw); struct gprs_rlcmac_rlc_ul_window *ulw);
uint32_t TBF_StartingTime_to_fn(const StartingTime_t *tbf_start_time, uint32_t curr_fn);
uint32_t TBF_Starting_Frame_Number_to_fn(const Starting_Frame_Number_t *tbf_start_fn, uint32_t curr_fn);

View File

@ -88,7 +88,7 @@ extern struct gprs_rlcmac_ctx *g_ctx;
struct gprs_rlcmac_entity *gprs_rlcmac_find_entity_by_tlli(uint32_t tlli); 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); struct gprs_rlcmac_dl_tbf *gprs_rlcmac_find_dl_tbf_by_tfi(uint8_t dl_tfi);
struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi); struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi);
int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia); int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia, uint32_t fn);
int gprs_rlcmac_handle_bcch_si13(const struct gsm48_system_information_type_13 *si13); int gprs_rlcmac_handle_bcch_si13(const struct gsm48_system_information_type_13 *si13);
int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim, int gprs_rlcmac_handle_gprs_dl_block(const struct osmo_gprs_rlcmac_prim *rlcmac_prim,
enum gprs_rlcmac_coding_scheme cs); enum gprs_rlcmac_coding_scheme cs);

View File

@ -12,3 +12,23 @@ struct gprs_rlcmac_rts_block_ind {
uint32_t rrbp2fn(uint32_t cur_fn, uint8_t rrbp); uint32_t rrbp2fn(uint32_t cur_fn, uint8_t rrbp);
int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_rts_block_ind *bi); int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_rts_block_ind *bi);
static inline bool fn_valid(uint32_t fn)
{
uint32_t f = fn % 13;
return f == 0 || f == 4 || f == 8;
}
#define GSM_MAX_FN_THRESH (GSM_MAX_FN >> 1)
/* 0: equal, -1: fn1 BEFORE fn2, 1: fn1 AFTER fn2 */
static inline int fn_cmp(uint32_t fn1, uint32_t fn2)
{
if (fn1 == fn2)
return 0;
/* FN1 goes before FN2: */
if ((fn1 < fn2 && (fn2 - fn1) < GSM_MAX_FN_THRESH) ||
(fn1 > fn2 && (fn1 - fn2) > GSM_MAX_FN_THRESH))
return -1;
/* FN1 goes after FN2: */
return 1;
}

View File

@ -20,9 +20,10 @@ enum gprs_rlcmac_tbf_ul_ass_type {
enum gprs_rlcmac_tbf_ul_ass_fsm_states { enum gprs_rlcmac_tbf_ul_ass_fsm_states {
GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE = 0, /* new created TBF */ GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE = 0, /* new created TBF */
GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS, /* wait for Immediate Assignment */ GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS, /* wait for Immediate Assignment */
GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1, /* Wait for Tbf Starting Time (1phase) */
GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ, /* wait PDCH sched (USF) */ GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ, /* wait PDCH sched (USF) */
GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS, /* Wait for PCU to send the new assignment */ GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS, /* Wait for PCU to send the new assignment */
GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK, /* Wait for scheduler to send PKT CTRL ACK */ GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2, /* Wait for Tbf Starting Time (2phase) */
GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL, /* Completed, will update TBF and return to IDLE state */ GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL, /* Completed, will update TBF and return to IDLE state */
}; };
@ -37,6 +38,8 @@ struct gprs_rlcmac_tbf_ul_ass_fsm_ctx {
uint8_t rach_req_ra; uint8_t rach_req_ra;
struct gprs_rlcmac_ul_tbf_allocation phase1_alloc; struct gprs_rlcmac_ul_tbf_allocation phase1_alloc;
struct gprs_rlcmac_ul_tbf_allocation phase2_alloc; struct gprs_rlcmac_ul_tbf_allocation phase2_alloc;
bool tbf_starting_time_exists;
uint32_t tbf_starting_time;
/* Number of packet resource request transmitted (T3168) */ /* Number of packet resource request transmitted (T3168) */
unsigned int pkt_res_req_proc_attempts; unsigned int pkt_res_req_proc_attempts;
}; };
@ -46,12 +49,14 @@ enum tbf_ul_ass_fsm_event {
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_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_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_RX_CCCH_IMM_ASS, /* (data: struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx *) */
GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME, /* Scheduler ticking reaches TBF Starting Time */
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_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: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, /* (data: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */
}; };
struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx { struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx {
uint8_t ts_nr; uint8_t ts_nr;
uint32_t fn;
const struct gsm48_imm_ass *ia; const struct gsm48_imm_ass *ia;
const IA_RestOctets_t *iaro; const IA_RestOctets_t *iaro;
}; };
@ -80,6 +85,8 @@ int gprs_rlcmac_tbf_ul_ass_start_from_dl_tbf_ack_nack(struct gprs_rlcmac_ul_tbf
bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_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_match_rach_req(struct gprs_rlcmac_ul_tbf *ul_tbf, uint8_t ra);
bool gprs_rlcmac_tbf_ul_ass_waiting_tbf_starting_time(const struct gprs_rlcmac_ul_tbf *ul_tbf);
void gprs_rlcmac_tbf_ul_ass_fn_tick(const struct gprs_rlcmac_ul_tbf *ul_tbf, uint32_t fn, uint8_t ts_nr);
bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi); bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi);
struct msgb *gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(const struct gprs_rlcmac_ul_tbf *ul_tbf, struct msgb *gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(const struct gprs_rlcmac_ul_tbf *ul_tbf,
const struct gprs_rlcmac_rts_block_ind *bi); const struct gprs_rlcmac_rts_block_ind *bi);

View File

@ -26,6 +26,7 @@
#include <osmocom/gprs/rlcmac/pdch_ul_controller.h> #include <osmocom/gprs/rlcmac/pdch_ul_controller.h>
#include <osmocom/gprs/rlcmac/rlcmac_private.h> #include <osmocom/gprs/rlcmac/rlcmac_private.h>
#include <osmocom/gprs/rlcmac/types_private.h> #include <osmocom/gprs/rlcmac/types_private.h>
#include <osmocom/gprs/rlcmac/sched.h>
/* TS 44.060 Table 10.4.5.1 states maximum RRBP is N + 26. Give extra space for time diff between Tx and Rx? */ /* TS 44.060 Table 10.4.5.1 states maximum RRBP is N + 26. Give extra space for time diff between Tx and Rx? */
#define MAX_FN_RESERVED (27 + 50) #define MAX_FN_RESERVED (27 + 50)
@ -39,20 +40,6 @@ const struct value_string gprs_rlcmac_pdch_ulc_poll_reason_names[] = {
{ 0, NULL } { 0, NULL }
}; };
#define GSM_MAX_FN_THRESH (GSM_MAX_FN >> 1)
/* 0: equal, -1: fn1 BEFORE fn2, 1: fn1 AFTER fn2 */
static inline int fn_cmp(uint32_t fn1, uint32_t fn2)
{
if (fn1 == fn2)
return 0;
/* FN1 goes before FN2: */
if ((fn1 < fn2 && (fn2 - fn1) < GSM_MAX_FN_THRESH) ||
(fn1 > fn2 && (fn1 - fn2) > GSM_MAX_FN_THRESH))
return -1;
/* FN1 goes after FN2: */
return 1;
}
struct gprs_rlcmac_pdch_ulc *gprs_rlcmac_pdch_ulc_alloc(void *ctx, uint8_t ts_nr) struct gprs_rlcmac_pdch_ulc *gprs_rlcmac_pdch_ulc_alloc(void *ctx, uint8_t ts_nr)
{ {
struct gprs_rlcmac_pdch_ulc *ulc; struct gprs_rlcmac_pdch_ulc *ulc;

View File

@ -165,12 +165,13 @@ struct gprs_rlcmac_ul_tbf *gprs_rlcmac_find_ul_tbf_by_tfi(uint8_t ul_tfi)
return NULL; 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) static int gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(uint8_t ts_nr, uint32_t fn, const struct gsm48_imm_ass *ia, const IA_RestOctets_t *iaro)
{ {
int rc = -ENOENT; int rc = -ENOENT;
struct gprs_rlcmac_entity *gre; struct gprs_rlcmac_entity *gre;
struct gprs_rlcmac_ul_tbf *ul_tbf; struct gprs_rlcmac_ul_tbf *ul_tbf;
struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx d = { struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx d = {
.fn = fn,
.ts_nr = ts_nr, .ts_nr = ts_nr,
.ia = ia, .ia = ia,
.iaro = iaro .iaro = iaro
@ -190,7 +191,7 @@ static int gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(uint8_t ts_nr, const struct gs
return rc; 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) static int gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(uint8_t ts_nr, uint32_t fn, const struct gsm48_imm_ass *ia, const IA_RestOctets_t *iaro)
{ {
int rc; int rc;
struct gprs_rlcmac_entity *gre; struct gprs_rlcmac_entity *gre;
@ -224,7 +225,7 @@ static int gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(uint8_t ts_nr, const struct gs
return rc; return rc;
} }
int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia) int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia, uint32_t fn)
{ {
int rc; int rc;
uint8_t ch_type, ch_subch, ch_ts; uint8_t ch_type, ch_subch, ch_ts;
@ -253,10 +254,10 @@ int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia)
case 1: /* iaro.u.lh.* (IA_RestOctetsLH_t) */ case 1: /* iaro.u.lh.* (IA_RestOctetsLH_t) */
switch (iaro.u.lh.lh0x.UnionType) { switch (iaro.u.lh.lh0x.UnionType) {
case 0: /* iaro.u.ll.lh0x.EGPRS_PktUlAss.* (IA_EGPRS_PktUlAss_t) */ case 0: /* iaro.u.ll.lh0x.EGPRS_PktUlAss.* (IA_EGPRS_PktUlAss_t) */
rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, ia, &iaro); rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, fn, ia, &iaro);
break; break;
case 1: /* iaro.u.ll.lh0x.MultiBlock_PktDlAss.* (IA_MultiBlock_PktDlAss_t) */ case 1: /* iaro.u.ll.lh0x.MultiBlock_PktDlAss.* (IA_MultiBlock_PktDlAss_t) */
rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, ia, &iaro); rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, fn, ia, &iaro);
break; break;
} }
/* TODO: iaro.u.lh.AdditionsR13.* (IA_AdditionsR13_t) */ /* TODO: iaro.u.lh.AdditionsR13.* (IA_AdditionsR13_t) */
@ -279,17 +280,17 @@ int gprs_rlcmac_handle_ccch_imm_ass(const struct gsm48_imm_ass *ia)
case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.* (GPRS_DynamicOrFixedAllocation_t) */ case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.* (GPRS_DynamicOrFixedAllocation_t) */
switch (iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.UnionType) { switch (iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.UnionType) {
case 0: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.DynamicAllocation (DynamicAllocation_t) */ case 0: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.DynamicAllocation (DynamicAllocation_t) */
rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, ia, &iaro); rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, fn, ia, &iaro);
break; break;
case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.FixedAllocationDummy (guint8) */ case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.FixedAllocationDummy (guint8) */
rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, ia, &iaro); rc = gprs_rlcmac_handle_ccch_imm_ass_ul_tbf(ch_ts, fn, ia, &iaro);
break; break;
} }
break; break;
} }
break; break;
case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Downlink_ImmAssignment* (Packet_Downlink_ImmAssignment_t) */ case 1: /* iaro.u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Downlink_ImmAssignment* (Packet_Downlink_ImmAssignment_t) */
rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, ia, &iaro); rc = gprs_rlcmac_handle_ccch_imm_ass_dl_tbf(ch_ts, fn, ia, &iaro);
break; break;
} }
break; break;

View File

@ -22,11 +22,14 @@
#include <stdint.h> #include <stdint.h>
#include <osmocom/core/logging.h> #include <osmocom/core/logging.h>
#include <osmocom/gsm/gsm0502.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gprs/rlcmac/rlcmac_private.h> #include <osmocom/gprs/rlcmac/rlcmac_private.h>
#include <osmocom/gprs/rlcmac/rlcmac_dec.h> #include <osmocom/gprs/rlcmac/rlcmac_dec.h>
#include <osmocom/gprs/rlcmac/rlc.h> #include <osmocom/gprs/rlcmac/rlc.h>
#include <osmocom/gprs/rlcmac/rlc_window_ul.h> #include <osmocom/gprs/rlcmac/rlc_window_ul.h>
#include <osmocom/gprs/rlcmac/sched.h>
#define LENGTH_TO_END 255 #define LENGTH_TO_END 255
/*! /*!
@ -422,3 +425,47 @@ int gprs_rlcmac_decode_gprs_acknack_bits(const Ack_Nack_Description_t *desc,
return num_blocks; return num_blocks;
} }
/* 12.21 Starting Frame Number Description */
uint32_t TBF_StartingTime_to_fn(const StartingTime_t *tbf_start_time, uint32_t curr_fn)
{
const struct gsm_time g_time = {
.t1 = tbf_start_time->N32,
.t2 = tbf_start_time->N51,
.t3 = tbf_start_time->N26
};
return gsm_gsmtime2fn(&g_time);
}
/* 12.21.2 Relative Frame Number Encoding */
static uint32_t k_to_fn(uint16_t k, uint32_t curr_fn)
{
uint32_t fn = 0;
switch (k % 3) {
case 0:
case 1:
fn = GSM_TDMA_FN_SUM(curr_fn, 4 + 4 * k + (k / 3));
if (!fn_valid(fn))
GSM_TDMA_FN_INC(fn);
break;
case 2:
fn = GSM_TDMA_FN_SUM(curr_fn, 5 + 4 * k + (k / 3));
break;
}
OSMO_ASSERT(fn_valid(fn));
return fn;
}
uint32_t TBF_Starting_Frame_Number_to_fn(const Starting_Frame_Number_t *tbf_start_fn, uint32_t curr_fn)
{
switch (tbf_start_fn->UnionType) {
case 0: /* 12.21.1 Absolute Frame Number Encoding */
return TBF_StartingTime_to_fn(&tbf_start_fn->u.StartingTime, curr_fn);
case 1: /* 12.21.2 Relative Frame Number Encoding */
return k_to_fn(tbf_start_fn->u.k, curr_fn);
default:
OSMO_ASSERT(0);
}
}

View File

@ -504,7 +504,8 @@ static int rlcmac_prim_handle_l1ctl_ccch_data_ind(struct osmo_gprs_rlcmac_prim *
switch (rlcmac_prim->l1ctl.ccch_data_ind.data[2]) { switch (rlcmac_prim->l1ctl.ccch_data_ind.data[2]) {
case GSM48_MT_RR_IMM_ASS: case GSM48_MT_RR_IMM_ASS:
rc = gprs_rlcmac_handle_ccch_imm_ass((struct gsm48_imm_ass *)rlcmac_prim->l1ctl.ccch_data_ind.data); rc = gprs_rlcmac_handle_ccch_imm_ass((struct gsm48_imm_ass *)rlcmac_prim->l1ctl.ccch_data_ind.data,
rlcmac_prim->l1ctl.ccch_data_ind.fn);
break; break;
case GSM48_MT_RR_SYSINFO_13: case GSM48_MT_RR_SYSINFO_13:
rc = gprs_rlcmac_handle_bcch_si13((struct gsm48_system_information_type_13 *)rlcmac_prim->l1ctl.ccch_data_ind.data); rc = gprs_rlcmac_handle_bcch_si13((struct gsm48_system_information_type_13 *)rlcmac_prim->l1ctl.ccch_data_ind.data);

View File

@ -41,12 +41,6 @@ struct tbf_sched_ctrl_candidates {
struct gprs_rlcmac_ul_tbf *ul_ass; /* PCU grants USF/SBA: transmit Pkt Res Req (2phase access)*/ 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)
{
uint32_t f = fn % 13;
return f == 0 || f == 4 || f == 8;
}
uint32_t rrbp2fn(uint32_t cur_fn, uint8_t rrbp) uint32_t rrbp2fn(uint32_t cur_fn, uint8_t rrbp)
{ {
uint32_t poll_fn; uint32_t poll_fn;
@ -210,7 +204,7 @@ static struct msgb *sched_select_ctrl_msg(const struct gprs_rlcmac_rts_block_ind
return msg; return msg;
} }
if (tbfs->poll_ul_ass) { if (tbfs->poll_ul_ass) {
msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(tbfs->poll_ul_ass, bi); msg = gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(tbfs->poll_ul_ass);
if (msg) if (msg)
return msg; return msg;
} }
@ -260,6 +254,15 @@ static struct msgb *sched_select_ul_dummy_ctrl_blk(const struct gprs_rlcmac_rts_
return gprs_rlcmac_ul_tbf_dummy_create(ul_tbf); return gprs_rlcmac_ul_tbf_dummy_create(ul_tbf);
} }
static void rts_tick(const struct gprs_rlcmac_rts_block_ind *bi)
{
struct gprs_rlcmac_entity *gre;
llist_for_each_entry(gre, &g_ctx->gre_list, entry) {
if (gre->ul_tbf && gprs_rlcmac_tbf_ul_ass_waiting_tbf_starting_time(gre->ul_tbf))
gprs_rlcmac_tbf_ul_ass_fn_tick(gre->ul_tbf, bi->fn, bi->ts);
}
}
int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_rts_block_ind *bi) int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_rts_block_ind *bi)
{ {
struct msgb *msg = NULL; struct msgb *msg = NULL;
@ -267,6 +270,8 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_rts_block_ind *bi)
struct osmo_gprs_rlcmac_prim *rlcmac_prim_tx; struct osmo_gprs_rlcmac_prim *rlcmac_prim_tx;
int rc = 0; int rc = 0;
rts_tick(bi);
get_ctrl_msg_tbf_candidates(bi, &tbf_cand); get_ctrl_msg_tbf_candidates(bi, &tbf_cand);
if ((msg = sched_select_ctrl_msg(bi, &tbf_cand))) if ((msg = sched_select_ctrl_msg(bi, &tbf_cand)))

View File

@ -24,6 +24,8 @@
#include <osmocom/core/tdef.h> #include <osmocom/core/tdef.h>
#include <osmocom/core/fsm.h> #include <osmocom/core/fsm.h>
#include <osmocom/core/bitvec.h> #include <osmocom/core/bitvec.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/gsm0502.h>
#include <osmocom/gprs/rlcmac/types.h> #include <osmocom/gprs/rlcmac/types.h>
#include <osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h> #include <osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h>
@ -32,6 +34,7 @@
#include <osmocom/gprs/rlcmac/sched.h> #include <osmocom/gprs/rlcmac/sched.h>
#include <osmocom/gprs/rlcmac/csn1_defs.h> #include <osmocom/gprs/rlcmac/csn1_defs.h>
#include <osmocom/gprs/rlcmac/rlcmac_enc.h> #include <osmocom/gprs/rlcmac/rlcmac_enc.h>
#include <osmocom/gprs/rlcmac/rlcmac_dec.h>
#include <osmocom/gprs/rlcmac/pdch_ul_controller.h> #include <osmocom/gprs/rlcmac/pdch_ul_controller.h>
#define X(s) (1 << (s)) #define X(s) (1 << (s))
@ -41,6 +44,7 @@ static const struct value_string tbf_ul_ass_fsm_event_names[] = {
{ GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, "START_DIRECT_2PHASE" }, { 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_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_RX_CCCH_IMM_ASS, "RX_CCCH_IMM_ASS" },
{ GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME, "TBF_STARTING_TIME" },
{ GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" }, { 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" }, { GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, "RX_PKT_UL_ASS" },
{ 0, NULL } { 0, NULL }
@ -49,9 +53,10 @@ static const struct value_string tbf_ul_ass_fsm_event_names[] = {
static const struct osmo_tdef_state_timeout tbf_ul_ass_fsm_timeouts[32] = { static const struct osmo_tdef_state_timeout tbf_ul_ass_fsm_timeouts[32] = {
[GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE] = { }, [GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE] = { },
[GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS] = { }, [GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS] = { },
[GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1] = { },
[GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ] = { }, [GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ] = { },
[GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS] = { .T = 3168 }, [GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_PKT_UL_ASS] = { .T = 3168 },
[GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK] = { }, [GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2] = { },
[GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL] = { }, [GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL] = { },
}; };
@ -141,6 +146,10 @@ static int handle_imm_ass(struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx, const stru
return -ENOTSUP; return -ENOTSUP;
case 1: /* d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.* (GPRS_DynamicOrFixedAllocation_t) */ case 1: /* d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.* (GPRS_DynamicOrFixedAllocation_t) */
ctx->ul_tbf->tx_cs = d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.CHANNEL_CODING_COMMAND + 1; ctx->ul_tbf->tx_cs = d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.CHANNEL_CODING_COMMAND + 1;
ctx->tbf_starting_time_exists = d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Exist_TBF_STARTING_TIME;
if (ctx->tbf_starting_time_exists)
ctx->tbf_starting_time = TBF_StartingTime_to_fn(&d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.TBF_STARTING_TIME,
d->fn);
LOGPFSML(ctx->fi, LOGL_INFO, "ImmAss initial CS=%s\n", gprs_rlcmac_mcs_name(ctx->ul_tbf->tx_cs)); LOGPFSML(ctx->fi, LOGL_INFO, "ImmAss initial CS=%s\n", gprs_rlcmac_mcs_name(ctx->ul_tbf->tx_cs));
switch (d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.UnionType) { switch (d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.UnionType) {
case 0: /* d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.DynamicAllocation (DynamicAllocation_t) */ case 0: /* d->iaro->u.hh.u.UplinkDownlinkAssignment.ul_dl.Packet_Uplink_ImmAssignment.Access.DynamicOrFixedAllocation.Allocation.DynamicAllocation (DynamicAllocation_t) */
@ -181,7 +190,11 @@ static int handle_pkt_ul_ass(struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx, const s
case 1: /* Dynamic Allocation (Dynamic_Allocation_t) */ case 1: /* Dynamic Allocation (Dynamic_Allocation_t) */
if (ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.Exist_UPLINK_TFI_ASSIGNMENT) 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; 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 */ /* TODO: P0, PR_MODE, USF_GRANULARITY, RLC_DATA_BLOCKS_GRANTED */
ctx->tbf_starting_time_exists = ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.Exist_TBF_Starting_Time;
if (ctx->tbf_starting_time_exists)
ctx->tbf_starting_time = TBF_Starting_Frame_Number_to_fn(&ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.TBF_Starting_Time,
d->fn);
switch (ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.UnionType) { switch (ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.UnionType) {
case 0: /* Timeslot_Allocation_t */ case 0: /* Timeslot_Allocation_t */
ts_alloc = &ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.u.Timeslot_Allocation[0]; ts_alloc = &ulass->u.PUA_GPRS_Struct.u.Dynamic_Allocation.u.Timeslot_Allocation[0];
@ -271,6 +284,42 @@ static void st_wait_ccch_imm_ass(struct osmo_fsm_inst *fi, uint32_t event, void
ev_rx_ccch_imm_ass_ctx = data; ev_rx_ccch_imm_ass_ctx = data;
if (handle_imm_ass(ctx, ev_rx_ccch_imm_ass_ctx) < 0) if (handle_imm_ass(ctx, ev_rx_ccch_imm_ass_ctx) < 0)
return; return;
if (ctx->tbf_starting_time_exists &&
fn_cmp(ctx->tbf_starting_time, ev_rx_ccch_imm_ass_ctx->fn) > 0) {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1);
return;
}
if (ctx->ass_type == GPRS_RLCMAC_TBF_UL_ASS_TYPE_1PHASE)
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
else
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ);
break;
default:
OSMO_ASSERT(0);
}
}
static void st_wait_tbf_starting_time1(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;
const struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx *ev_rx_ccch_imm_ass_ctx;
switch (event) {
case GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS:
ev_rx_ccch_imm_ass_ctx = data;
if (handle_imm_ass(ctx, ev_rx_ccch_imm_ass_ctx) < 0)
return;
if (ctx->tbf_starting_time_exists &&
fn_cmp(ctx->tbf_starting_time, ev_rx_ccch_imm_ass_ctx->fn) > 0) {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1);
return;
}
if (ctx->ass_type == GPRS_RLCMAC_TBF_UL_ASS_TYPE_1PHASE)
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
else
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_TBF_STARTING_TIME:
if (ctx->ass_type == GPRS_RLCMAC_TBF_UL_ASS_TYPE_1PHASE) if (ctx->ass_type == GPRS_RLCMAC_TBF_UL_ASS_TYPE_1PHASE)
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL); tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
else else
@ -317,7 +366,11 @@ static void st_wait_pkt_ul_ass(struct osmo_fsm_inst *fi, uint32_t event, void *d
gprs_rlcmac_pdch_ulc_reserve(g_ctx->sched.ulc[d->ts_nr], poll_fn, gprs_rlcmac_pdch_ulc_reserve(g_ctx->sched.ulc[d->ts_nr], poll_fn,
GPRS_RLCMAC_PDCH_ULC_POLL_UL_ASS, GPRS_RLCMAC_PDCH_ULC_POLL_UL_ASS,
ul_tbf_as_tbf(ctx->ul_tbf)); ul_tbf_as_tbf(ctx->ul_tbf));
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK); }
if (ctx->tbf_starting_time_exists &&
fn_cmp(ctx->tbf_starting_time, d->fn) > 0) {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2);
} else { } else {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL); tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
} }
@ -327,17 +380,34 @@ static void st_wait_pkt_ul_ass(struct osmo_fsm_inst *fi, uint32_t event, void *d
} }
} }
static void st_sched_pkt_ctrl_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data) static void st_wait_tbf_starting_time2(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; struct tbf_ul_ass_ev_rx_pkt_ul_ass_ctx *d;
int rc;
switch (event) { switch (event) {
case GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG: case GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS:
data_ctx = (struct tbf_ul_ass_ev_create_rlcmac_msg_ctx *)data; d = data;
data_ctx->msg = gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(ctx->ul_tbf); rc = handle_pkt_ul_ass(ctx, d);
if (!data_ctx->msg) if (rc < 0)
return; 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.
/* 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));
}
if (ctx->tbf_starting_time_exists &&
fn_cmp(ctx->tbf_starting_time, d->fn) > 0) {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2);
} else {
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
}
case GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME:
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL); tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL);
break; break;
default: default:
@ -378,11 +448,23 @@ static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = {
.in_event_mask = .in_event_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS), X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS),
.out_state_mask = .out_state_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1) |
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_COMPL), X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL),
.name = "WAIT_CCCH_IMM_ASS", .name = "WAIT_CCCH_IMM_ASS",
.action = st_wait_ccch_imm_ass, .action = st_wait_ccch_imm_ass,
}, },
[GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1] = {
.in_event_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS) |
X(GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME),
.out_state_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1) |
X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ) |
X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL),
.name = "WAIT_TBF_STARTING_TIME1",
.action = st_wait_tbf_starting_time1,
},
[GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ] = { [GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ] = {
.in_event_mask = .in_event_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG), X(GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG),
@ -396,18 +478,21 @@ static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = {
X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS), X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS),
.out_state_mask = .out_state_mask =
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_SCHED_PKT_CTRL_ACK) | X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2) |
X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL), X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL),
.name = "WAIT_PKT_UL_ASS", .name = "WAIT_PKT_UL_ASS",
.action = st_wait_pkt_ul_ass, .action = st_wait_pkt_ul_ass,
}, },
[GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_CTRL_ACK] = { [GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2] = {
.in_event_mask = .in_event_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG), X(GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS) |
X(GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME),
.out_state_mask = .out_state_mask =
X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ) |
X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2) |
X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL), X(GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL),
.name = "SCHED_PKT_CTRL_ACK", .name = "WAIT_TBF_STARTING_TIME2",
.action = st_sched_pkt_ctrl_ack, .action = st_wait_tbf_starting_time2,
}, },
[GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL] = { [GPRS_RLCMAC_TBF_UL_ASS_ST_COMPL] = {
.in_event_mask = 0, .in_event_mask = 0,
@ -539,6 +624,23 @@ bool gprs_rlcmac_tbf_ul_ass_match_rach_req(struct gprs_rlcmac_ul_tbf *ul_tbf, ui
ul_tbf->ul_ass_fsm.rach_req_ra == ra; ul_tbf->ul_ass_fsm.rach_req_ra == ra;
} }
bool gprs_rlcmac_tbf_ul_ass_waiting_tbf_starting_time(const struct gprs_rlcmac_ul_tbf *ul_tbf)
{
return ul_tbf->ul_ass_fsm.fi->state == GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME1 ||
ul_tbf->ul_ass_fsm.fi->state == GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_TBF_STARTING_TIME2;
}
/* The scheduled ticks the new FN, which may trigger changes internally if TBF Starting Time is reached */
void gprs_rlcmac_tbf_ul_ass_fn_tick(const struct gprs_rlcmac_ul_tbf *ul_tbf, uint32_t fn, uint8_t ts_nr)
{
OSMO_ASSERT(gprs_rlcmac_tbf_ul_ass_waiting_tbf_starting_time(ul_tbf));
OSMO_ASSERT(ul_tbf->ul_ass_fsm.tbf_starting_time_exists);
if (fn != ul_tbf->ul_ass_fsm.tbf_starting_time)
return;
osmo_fsm_inst_dispatch(ul_tbf->ul_ass_fsm.fi, GPRS_RLCMAC_TBF_UL_ASS_EV_TBF_STARTING_TIME, NULL);
}
enum gprs_rlcmac_tbf_ul_ass_fsm_states gprs_rlcmac_tbf_ul_ass_state(const struct gprs_rlcmac_ul_tbf *ul_tbf) enum gprs_rlcmac_tbf_ul_ass_fsm_states gprs_rlcmac_tbf_ul_ass_state(const struct gprs_rlcmac_ul_tbf *ul_tbf)
{ {
const struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = &ul_tbf->ul_ass_fsm; const struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx = &ul_tbf->ul_ass_fsm;

View File

@ -659,16 +659,14 @@ DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_DATA.indication
DLGLOBAL INFO TS=7 FN=26 Rx Pkt UL ASS 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 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 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 UL_TBF_ASS{WAIT_PKT_UL_ASS}: state_chg to COMPLETED
DLGLOBAL DEBUG 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}: Received Event UL_ASS_COMPL
DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0xc0 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{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_RTS.indication DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_RTS.indication
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Tx Packet Control Ack
DLGLOBAL DEBUG 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) Sending new block at BSN 0, CS=CS-2
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Dequeue next LLC (len=14) 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 -- Chunk with length 14 is less than remaining space (30): add length header to delimit LLC frame