encoding: use CSN.1 codec to generate Packet Uplink Assignment

It's quite odd to see that in write_packet_downlink_assignment()
we initialize an 'RlcMacDownlink_t', so then the caller can use
the power of CSN.1 codec to generate the final sequence of bytes
to be transmitted, while in write_packet_uplink_assignment() we
already compose the final RLC/MAC message straight away using
the low-level bitvec API (like bitvec_write_field()).

I guess the reason is that at the time of writing this code, the
CSN.1 codec was not stable enough, so it was safer to generate
the message 'by hand'.  This would also explain why we *decode*
the final RLC/MAC message in create_ul_ass() right after encoding.

Rewrite write_packet_uplink_assignment(), so now it initializes
a caller-provided 'RlcMacDownlink_t' structure.  Given that it's
allocated on heap using talloc_zero(), do not initialize presence
indicators of fields that are not present in the message.

This would facilitate handling of frequency hopping parameters
in the upcoming changes, in particular we can now introduce a
function that would compose Frequency Parameters IE for both
write_packet_{downlink,uplink}_assignment().

Tested manually by running a GPRS-enabled network, as well as by
running test cases from ttcn3-pcu-test => no regressions observed.

Change-Id: I2850b91e0043cdca8ae7498a5fc727eeedd029b6
Related: SYS#4868, OS#4547
This commit is contained in:
Vadim Yanitskiy 2020-08-22 02:05:28 +07:00
parent 962d717f41
commit db56a3563e
3 changed files with 108 additions and 78 deletions

View File

@ -536,95 +536,125 @@ int Encoding::write_immediate_assignment(
return plen;
}
/* generate uplink assignment */
/* Generate Packet Uplink Assignment as per 3GPP TS 44.060, section 11.2.29.
* NOTE: 'block' is expected to be zero-initialized by the caller. */
void Encoding::write_packet_uplink_assignment(
bitvec * dest, uint8_t old_tfi,
RlcMacDownlink_t * block, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
const struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t rrbp, uint8_t alpha,
uint8_t gamma, int8_t ta_idx, bool use_egprs)
{
// TODO We should use our implementation of encode RLC/MAC Control messages.
unsigned wp = 0;
uint8_t ts;
/* timeslot assigned for the Continuous Timing Advance procedure */
uint8_t ta_ts = 0; /* FIXME: supply it as parameter from caller */
Packet_Uplink_Assignment_t *pua;
Packet_Timing_Advance_t *pta;
Frequency_Parameters_t *fp;
Dynamic_Allocation_t *da;
bitvec_write_field(dest, &wp,0x1,2); // Payload Type
bitvec_write_field(dest, &wp,rrbp,2); // Uplink block with TDMA framenumber (N+13)
bitvec_write_field(dest, &wp,poll,1); // Suppl/Polling Bit
bitvec_write_field(dest, &wp,0x0,3); // Uplink state flag
bitvec_write_field(dest, &wp,0xa,6); // MESSAGE TYPE
/* RLC/MAC control block without the optional RLC/MAC control header */
block->PAYLOAD_TYPE = 0x01; // Payload Type
block->RRBP = rrbp; // RRBP (e.g. N+13)
block->SP = poll; // RRBP field is valid
block->USF = 0x00; // Uplink state flag
bitvec_write_field(dest, &wp,0x0,2); // Page Mode
/* See 3GPP TS 44.060, section 11.2.29 */
pua = &block->u.Packet_Uplink_Assignment;
pua->MESSAGE_TYPE = 0x0a; // Packet Uplink Assignment
pua->PAGE_MODE = 0x00; // Normal Paging
bitvec_write_field(dest, &wp,0x0,1); // switch PERSIST_LEVEL: off
/* TLLI or Global (UL/DL) TFI */
if (use_tlli) {
bitvec_write_field(dest, &wp,0x2,2); // switch TLLI : on
bitvec_write_field(dest, &wp,tlli,32); // TLLI
pua->ID.UnionType = 0x01;
pua->ID.u.TLLI = tlli;
} else {
bitvec_write_field(dest, &wp,0x0,1); // switch TFI : on
bitvec_write_field(dest, &wp,old_downlink,1); // 0=UPLINK TFI, 1=DL TFI
bitvec_write_field(dest, &wp,old_tfi,5); // TFI
pua->ID.UnionType = 0x00;
pua->ID.u.Global_TFI.UnionType = old_downlink;
pua->ID.u.Global_TFI.u.UPLINK_TFI = old_tfi;
}
/* GPRS/EGPRS specific parameters */
pua->UnionType = use_egprs ? 0x01 : 0x00;
if (!use_egprs) {
bitvec_write_field(dest, &wp,0x0,1); // Message escape
bitvec_write_field(dest, &wp, mcs_chan_code(tbf->current_cs()), 2); // CHANNEL_CODING_COMMAND
bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
write_ta_ie(dest, wp, tbf->ta(), ta_idx, ta_ts);
} else { /* EPGRS */
bitvec_write_field(dest, &wp,0x1,1); // Message escape
bitvec_write_field(dest, &wp,0x0,2); // EGPRS message contents
bitvec_write_field(dest, &wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI
bitvec_write_field(dest, &wp,0x0,1); // No COMPACT reduced MA
bitvec_write_field(dest, &wp, mcs_chan_code(tbf->current_cs()), 4); // EGPRS Modulation and Coding IE
/* 0: no RESEGMENT, 1: Segmentation*/
bitvec_write_field(dest, &wp, 0x1, 1);
write_ws(dest, &wp, tbf->window_size()); // EGPRS Window Size
bitvec_write_field(dest, &wp,0x0,1); // No Access Technologies Request
bitvec_write_field(dest, &wp,0x0,1); // No ARAC RETRANSMISSION REQUEST
bitvec_write_field(dest, &wp,0x1,1); // TLLI_BLOCK_CHANNEL_CODING
bitvec_write_field(dest, &wp,0x0,1); // No BEP_PERIOD2
write_ta_ie(dest, wp, tbf->ta(), ta_idx, ta_ts);
bitvec_write_field(dest, &wp,0x0,1); // No Packet Extended Timing Advance
PUA_GPRS_t *gprs = &pua->u.PUA_GPRS_Struct;
/* Use the commanded CS/MSC value during the content resolution */
gprs->CHANNEL_CODING_COMMAND = mcs_chan_code(tbf->current_cs());
gprs->TLLI_BLOCK_CHANNEL_CODING = 0x01; // ^^^
/* Dynamic allocation */
gprs->UnionType = 0x01;
/* Frequency Parameters IE is present */
gprs->Exist_Frequency_Parameters = 0x01;
/* Common parameters to be set below */
pta = &gprs->Packet_Timing_Advance;
fp = &gprs->Frequency_Parameters;
da = &gprs->u.Dynamic_Allocation;
} else {
PUA_EGPRS_00_t *egprs = &pua->u.PUA_EGPRS_Struct.u.PUA_EGPRS_00;
pua->u.PUA_EGPRS_Struct.UnionType = 0x00; // 'Normal' EGPRS, not EGPRS2
/* Use the commanded CS/MSC value during the content resolution */
egprs->EGPRS_CHANNEL_CODING_COMMAND = mcs_chan_code(tbf->current_cs());
egprs->TLLI_BLOCK_CHANNEL_CODING = 0x01; // ^^^
egprs->RESEGMENT = 0x01; // Enable segmentation
egprs->EGPRS_WindowSize = tbf->window_size();
/* Dynamic allocation */
egprs->UnionType = 0x01;
/* Frequency Parameters IE is present */
egprs->Exist_Frequency_Parameters = 0x01;
/* Common parameters to be set below */
pta = &egprs->Packet_Timing_Advance;
fp = &egprs->Frequency_Parameters;
da = &egprs->u.Dynamic_Allocation;
}
#if 1
bitvec_write_field(dest, &wp,0x1,1); // Frequency Parameters information elements = present
bitvec_write_field(dest, &wp,tbf->tsc(),3); // Training Sequence Code (TSC)
bitvec_write_field(dest, &wp,0x0,2); // ARFCN = present
bitvec_write_field(dest, &wp,tbf->trx->arfcn,10); // ARFCN
#else
bitvec_write_field(dest, &wp,0x0,1); // Frequency Parameters = off
#endif
bitvec_write_field(dest, &wp,0x1,2); // Dynamic Allocation
bitvec_write_field(dest, &wp,0x0,1); // Extended Dynamic Allocation = off
bitvec_write_field(dest, &wp,0x0,1); // P0 = off
bitvec_write_field(dest, &wp,0x0,1); // USF_GRANULARITY
bitvec_write_field(dest, &wp,0x1,1); // switch TFI : on
bitvec_write_field(dest, &wp,tbf->tfi(),5);// TFI
bitvec_write_field(dest, &wp,0x0,1); //
bitvec_write_field(dest, &wp,0x0,1); // TBF Starting Time = off
if (alpha || gamma) {
bitvec_write_field(dest, &wp,0x1,1); // Timeslot Allocation with Power Control
bitvec_write_field(dest, &wp,alpha,4); // ALPHA
} else
bitvec_write_field(dest, &wp,0x0,1); // Timeslot Allocation
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
bitvec_write_field(dest, &wp,0x1,1); // USF_TN(i): on
bitvec_write_field(dest, &wp,tbf->m_usf[ts],3); // USF_TN(i)
if (alpha || gamma)
bitvec_write_field(dest, &wp,gamma,5); // GAMMA power control parameter
} else
bitvec_write_field(dest, &wp,0x0,1); // USF_TN(i): off
/* Packet Timing Advance (if known) */
if (tbf->ta() <= 63) { /* { 0 | 1 < TIMING_ADVANCE_VALUE : bit (6) > } */
pta->Exist_TIMING_ADVANCE_VALUE = 0x01; // Present
pta->TIMING_ADVANCE_VALUE = tbf->ta();
}
/* Continuous Timing Advance Control */
if (ta_idx >= 0 && ta_idx < 16) {
pta->Exist_IndexAndtimeSlot = 0x01; // Present
pta->TIMING_ADVANCE_TIMESLOT_NUMBER = 0; // FIXME!
pta->TIMING_ADVANCE_INDEX = ta_idx;
}
/* Frequency Parameters IE */
fp->TSC = tbf->tsc(); // Training Sequence Code (TSC)
fp->UnionType = 0x00; // Single ARFCN
fp->u.ARFCN = tbf->trx->arfcn;
/* Dynamic allocation parameters */
da->USF_GRANULARITY = 0x00;
/* Assign an Uplink TFI */
da->Exist_UPLINK_TFI_ASSIGNMENT = 0x01;
da->UPLINK_TFI_ASSIGNMENT = tbf->tfi();
/* Timeslot Allocation with or without Power Control */
da->UnionType = (alpha || gamma) ? 0x01 : 0x00;
if (da->UnionType == 0x01)
da->u.Timeslot_Allocation_Power_Ctrl_Param.ALPHA = alpha;
for (unsigned int tn = 0; tn < 8; tn++) {
if (tbf->pdch[tn] == NULL)
continue;
if (da->UnionType == 0x01) {
Timeslot_Allocation_Power_Ctrl_Param_t *params = \
&da->u.Timeslot_Allocation_Power_Ctrl_Param;
params->Slot[tn].Exist = 0x01; // Enable this timeslot
params->Slot[tn].USF_TN = tbf->m_usf[tn]; // USF_TN(i)
params->Slot[tn].GAMMA_TN = gamma;
} else {
Timeslot_Allocation_t *slot = &da->u.Timeslot_Allocation[tn];
slot->Exist = 0x01; // Enable this timeslot
slot->USF_TN = tbf->m_usf[tn]; // USF_TN(i)
}
}
// bitvec_write_field(dest, &wp,0x0,1); // Measurement Mapping struct not present
}

View File

@ -58,7 +58,7 @@ public:
);
static void write_packet_uplink_assignment(
bitvec * dest, uint8_t old_tfi,
RlcMacDownlink_t * block, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
const struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t rrbp,
uint8_t alpha, uint8_t gamma, int8_t ta_idx,

View File

@ -1368,16 +1368,16 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn, uint8_t ts)
bitvec_unhex(&bv, DUMMY_VEC);
LOGPTBF(new_tbf, LOGL_INFO, "start Packet Uplink Assignment (PACCH)\n");
Encoding::write_packet_uplink_assignment(&bv, m_tfi,
mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Encoding::write_packet_uplink_assignment(mac_control_block, m_tfi,
(direction == GPRS_RLCMAC_DL_TBF), tlli(),
is_tlli_valid(), new_tbf, 1, rrbp, bts_data()->alpha,
bts_data()->gamma, -1, is_egprs_enabled());
mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
LOGP(DTBF, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Uplink Assignment +++++++++++++++++++++++++\n");
rc = decode_gsm_rlcmac_downlink(&bv, mac_control_block);
rc = encode_gsm_rlcmac_downlink(&bv, mac_control_block);
if (rc < 0) {
LOGP(DTBF, LOGL_ERROR, "Decoding of Packet Uplink Ass failed (%d)\n", rc);
LOGP(DTBF, LOGL_ERROR, "Encoding of Packet Uplink Ass failed (%d)\n", rc);
goto free_ret;
}
LOGP(DTBF, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n");