rlcmac: dl_tbf: Improve logic requesting a new UL TBF
Change-Id: I702872ba32a410bb5f09943af3cdadca482562db
This commit is contained in:
parent
eb622ef09c
commit
9a212cc2b6
|
@ -20,6 +20,10 @@ struct gprs_rlcmac_entity {
|
|||
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);
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ struct msgb *gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(const struct gprs_rlcmac_ul_
|
|||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -32,14 +32,11 @@ struct gprs_rlcmac_tbf_ul_ass_fsm_ctx {
|
|||
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 @@ struct gprs_rlcmac_tbf_ul_ass_fsm_ctx {
|
|||
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 @@ struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx {
|
|||
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 @@ void gprs_rlcmac_tbf_ul_ass_fsm_destructor(struct gprs_rlcmac_ul_tbf *ul_tbf);
|
|||
|
||||
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);
|
||||
|
|
|
@ -66,6 +66,40 @@ void gprs_rlcmac_entity_free(struct gprs_rlcmac_entity *gre)
|
|||
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 @@ int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_p
|
|||
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)
|
||||
|
|
|
@ -358,6 +358,58 @@ static int gprs_rlcmac_handle_pkt_ul_ack_nack(const struct osmo_gprs_rlcmac_prim
|
|||
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 @@ static int gprs_rlcmac_handle_gprs_dl_ctrl_block(const struct osmo_gprs_rlcmac_p
|
|||
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,
|
||||
|
|
|
@ -386,6 +386,7 @@ void gprs_rlcmac_enc_prepare_pkt_downlink_ack_nack(RlcMacUplink_t *block, const
|
|||
{
|
||||
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 @@ void gprs_rlcmac_enc_prepare_pkt_downlink_ack_nack(RlcMacUplink_t *block, const
|
|||
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 @@ void gprs_rlcmac_enc_prepare_pkt_downlink_ack_nack(RlcMacUplink_t *block, const
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ struct tbf_sched_ctrl_candidates {
|
|||
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 @@ static void get_ctrl_msg_tbf_candidates(const struct gprs_rlcmac_rts_block_ind *
|
|||
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 @@ static struct msgb *sched_select_ctrl_msg(const struct gprs_rlcmac_rts_block_ind
|
|||
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)
|
||||
|
|
|
@ -261,6 +261,21 @@ int gprs_rlcmac_ul_tbf_handle_pkt_ul_ack_nack(struct gprs_rlcmac_ul_tbf *ul_tbf,
|
|||
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 @@ free_ret:
|
|||
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)
|
||||
|
|
|
@ -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 @@ static int handle_imm_ass(struct gprs_rlcmac_tbf_ul_ass_fsm_ctx *ctx, const stru
|
|||
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 @@ static void st_idle(struct osmo_fsm_inst *fi, uint32_t event, void *data)
|
|||
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_sched_pkt_res_req(struct osmo_fsm_inst *fi, uint32_t event, void
|
|||
|
||||
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_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)
|
||||
{
|
||||
//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 @@ static void st_compl_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
|
|||
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 @@ static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = {
|
|||
[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 @@ static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = {
|
|||
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 @@ static int tbf_ul_ass_fsm_timer_cb(struct osmo_fsm_inst *fi)
|
|||
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 @@ int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf
|
|||
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 @@ bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const s
|
|||
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;
|
||||
};
|
||||
|
|
|
@ -295,6 +295,75 @@ static void ul_ack_nack_mark(Ack_Nack_Description_t *ack_desc, unsigned int idx,
|
|||
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 @@ static void test_dl_tbf_ccch_assign(void)
|
|||
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 @@ int main(int argc, char *argv[])
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -620,3 +620,70 @@ 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 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
|
||||
|
|
|
@ -117,3 +117,12 @@ test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=
|
|||
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 ===
|
||||
|
|
Loading…
Reference in New Issue