diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 1d4fdcd538de1c9be3423fd7c4ce94b20d9bbc8e..5717b328057c7bf3725aa525714a7221e1ae4210 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -180,7 +180,7 @@ uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, memcpy(harq_process_ul_ue->a, ulsch_input_buffer, harq_process_ul_ue->TBS/8); #ifdef DEBUG_MAC_PDU - LOG_I(PHY, "Printing MAC PDU to be encoded: \n"); + LOG_I(PHY, "Printing MAC PDU to be encoded, TBS is: %d \n", harq_process_ul_ue->TBS/8); for (i = 0; i < harq_process_ul_ue->TBS / 8; i++) { printf("0x%02x",harq_process_ul_ue->a[i]); } diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 3c727738cfcad18fc30761b320f0523980c75147..4dd67d373f2894dd66ba0ebd587cb54671ade64a 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -316,6 +316,7 @@ void nr_fill_rx_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int UE_id, gNB->UL_INFO.rx_ind.sfn_sf = frame<<4| slot_rx; gNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; + gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list->rx_indication_rel8.length = gNB->ulsch[UE_id][0]->harq_processes[harq_pid]->TBS>>3; pdu = &gNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus]; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 564899ddcc84b26f942a46dfda35a777fb3973ce..476fb6858482e93383222e71aaafb55d78499475 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -1295,14 +1295,3 @@ uint8_t ul_subframe2_k_phich(COMMON_channels_t *cc, sub_frame_t ul_subframe); /* Main loop of MAC itti message handling */ void *mac_enb_task(void *arg); -unsigned char -nr_generate_ulsch_header(uint8_t *mac_header, - uint8_t num_sdus, - uint8_t short_padding, - uint16_t *sdu_lengths, - uint8_t *sdu_lcids, - POWER_HEADROOM_CMD *power_headroom, - uint16_t *crnti, - BSR_SHORT *truncated_bsr, - BSR_SHORT *short_bsr, - BSR_LONG *long_bsr, unsigned short post_padding); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h new file mode 100644 index 0000000000000000000000000000000000000000..cb004e0c23d6f0468db3bfda693e368a0be2a01f --- /dev/null +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -0,0 +1,138 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/* \file nr_mac.h + * \brief common MAC data structures, constant, and function prototype + * \author R. Knopp, K.H. HSU, G. Casati + * \date 2019 + * \version 0.1 + * \company Eurecom / NTUST / Fraunhofer IIS + * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr, guido.casati@iis.fraunhofer.de + * \note + * \warning + */ + +#ifndef __LAYER2_NR_MAC_H__ +#define __LAYER2_NR_MAC_H__ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NR_BCCH_DL_SCH 3 // SI + +#define NR_BCCH_BCH 5 // MIB + +// For both DL/UL-SCH +// Except: +// - UL/DL-SCH: fixed-size MAC CE(known by LCID) +// - UL/DL-SCH: padding +// - UL-SCH: MSG3 48-bits +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// |0|1|2|3|4|5|6|7| bit-wise +// |R|F| LCID | +// | L | +// | L | + +// For both DL/UL-SCH +// For: +// - UL/DL-SCH: fixed-size MAC CE(known by LCID) +// - UL/DL-SCH: padding, for single/multiple 1-oct padding CE(s) +// - UL-SCH: MSG3 48-bits +// |0|1|2|3|4|5|6|7| bit-wise +// |R|R| LCID | +// LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; +// L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; +// F: lenght of L is 0:8 or 1:16 bits wide +// R: Reserved bit, set to zero. + +typedef struct { + uint8_t LCID:6; // octet 1 [5:0] + uint8_t F:1; // octet 1 [6] + uint8_t R:1; // octet 1 [7] + uint8_t L:8; // octet 2 [7:0] +} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_SHORT; + +typedef struct { + uint8_t LCID:6; // octet 1 [5:0] + uint8_t F:1; // octet 1 [6] + uint8_t R:1; // octet 1 [7] + uint8_t L1:8; // octet 2 [7:0] + uint8_t L2:8; // octet 3 [7:0] +} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_LONG; + +typedef struct { + uint8_t LCID:6; // octet 1 [5:0] + uint8_t R:2; // octet 1 [7:6] +} __attribute__ ((__packed__)) NR_MAC_SUBHEADER_FIXED; + +// 38.321 ch. 6.1.3.4 +typedef struct { + uint8_t TA_COMMAND:6; // octet 1 [5:0] + uint8_t TAGID:2; // octet 1 [7:6] +} __attribute__ ((__packed__)) NR_MAC_CE_TA; + +// 38.321 ch6.2.1, 38.331 +#define DL_SCH_LCID_CCCH 0x00 +#define DL_SCH_LCID_DCCH 0x01 +#define DL_SCH_LCID_DCCH1 0x02 +#define DL_SCH_LCID_DTCH 0x03 +#define DL_SCH_LCID_RECOMMENDED_BITRATE 0x2F +#define DL_SCH_LCID_SP_ZP_CSI_RS_RES_SET_ACT 0x30 +#define DL_SCH_LCID_PUCCH_SPATIAL_RELATION_ACT 0x31 +#define DL_SCH_LCID_SP_SRS_ACTIVATION 0x32 +#define DL_SCH_LCID_SP_CSI_REP_PUCCH_ACT 0x33 +#define DL_SCH_LCID_TCI_STATE_IND_UE_SPEC_PDCCH 0x34 +#define DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH 0x35 +#define DL_SCH_LCID_APERIODIC_CSI_TRI_STATE_SUBSEL 0x36 +#define DL_SCH_LCID_SP_CSI_RS_CSI_IM_RES_SET_ACT 0X37 +#define DL_SCH_LCID_DUPLICATION_ACT 0X38 +#define DL_SCH_LCID_SCell_ACT_4_OCT 0X39 +#define DL_SCH_LCID_SCell_ACT_1_OCT 0X3A +#define DL_SCH_LCID_L_DRX 0x3B +#define DL_SCH_LCID_DRX 0x3C +#define DL_SCH_LCID_TA_COMMAND 0x3D +#define DL_SCH_LCID_CON_RES_ID 0x3E +#define DL_SCH_LCID_PADDING 0x3F + +#define UL_SCH_LCID_CCCH 0x00 +#define UL_SCH_LCID_SRB1 0x01 +#define UL_SCH_LCID_SRB2 0x02 +#define UL_SCH_LCID_DTCH 0x03 +#define UL_SCH_LCID_SRB3 0x04 +#define UL_SCH_LCID_CCCH_MSG3 0x21 +#define UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY 0x35 +#define UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT 0x36 +#define UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION 0x37 +#define UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT 0x38 +#define UL_SCH_LCID_SINGLE_ENTRY_PHR 0x39 +#define UL_SCH_LCID_C_RNTI 0x3A +#define UL_SCH_LCID_S_TRUNCATED_BSR 0x3B +#define UL_SCH_LCID_L_TRUNCATED_BSR 0x3C +#define UL_SCH_LCID_S_BSR 0x3D +#define UL_SCH_LCID_L_BSR 0x3E +#define UL_SCH_LCID_PADDING 0x3F + + +#endif /*__LAYER2_MAC_H__ */ + diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 9d75b06fa54840e4397bbcb7cb14d358a97e14c5..534f3bf9c3e6bbdd193526d917f1ed3cb1abf601 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -53,6 +53,13 @@ #include "PHY/defs_nr_common.h" #define NB_NR_UE_MAC_INST 1 +/*!\brief Maximum number of logical channl group IDs */ +#define MAX_NUM_LCGID 4 +/*!\brief Maximum number of logical chanels */ +#define MAX_NUM_LCID 11 + +/*!\brief value for indicating BSR Timer is not running */ +#define NR_MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) typedef enum { SFN_C_MOD_2_EQ_0, @@ -60,6 +67,86 @@ typedef enum { SFN_C_IMPOSSIBLE } SFN_C_TYPE; +#define UL_SCH_LCID_CCCH 0x00 +#define UL_SCH_LCID_SRB1 0x01 +#define UL_SCH_LCID_SRB2 0x02 +#define UL_SCH_LCID_DTCH 0x03 +#define UL_SCH_LCID_SRB3 0x04 +#define UL_SCH_LCID_CCCH_MSG3 0x21 +#define UL_SCH_LCID_RECOMMENDED_BITRATE_QUERY 0x35 +#define UL_SCH_LCID_MULTI_ENTRY_PHR_4_OCT 0x36 +#define UL_SCH_LCID_CONFIGURED_GRANT_CONFIRMATION 0x37 +#define UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT 0x38 +#define UL_SCH_LCID_SINGLE_ENTRY_PHR 0x39 +#define UL_SCH_LCID_C_RNTI 0x3A +#define UL_SCH_LCID_S_TRUNCATED_BSR 0x3B +#define UL_SCH_LCID_L_TRUNCATED_BSR 0x3C +#define UL_SCH_LCID_S_BSR 0x3D +#define UL_SCH_LCID_L_BSR 0x3E +#define UL_SCH_LCID_PADDING 0x3F + +// LTE structure, might need to be adapted for NR +typedef struct { + /// buffer status for each lcgid + uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology + /// keep the number of bytes in rlc buffer for each lcgid + int32_t BSR_bytes[MAX_NUM_LCGID]; + /// after multiplexing buffer remain for each lcid + int32_t LCID_buffer_remain[MAX_NUM_LCID]; + /// sum of all lcid buffer size + uint16_t All_lcid_buffer_size_lastTTI; + /// buffer status for each lcid + uint8_t LCID_status[MAX_NUM_LCID]; + /// SR pending as defined in 36.321 + uint8_t SR_pending; + /// SR_COUNTER as defined in 36.321 + uint16_t SR_COUNTER; + /// logical channel group ide for each LCID + uint8_t LCGID[MAX_NUM_LCID]; + /// retxBSR-Timer, default value is sf2560 + uint16_t retxBSR_Timer; + /// retxBSR_SF, number of subframe before triggering a regular BSR + uint16_t retxBSR_SF; + /// periodicBSR-Timer, default to infinity + uint16_t periodicBSR_Timer; + /// periodicBSR_SF, number of subframe before triggering a periodic BSR + uint16_t periodicBSR_SF; + /// default value is 0: not configured + uint16_t sr_ProhibitTimer; + /// sr ProhibitTime running + uint8_t sr_ProhibitTimer_Running; + /// default value to n5 + uint16_t maxHARQ_Tx; + /// default value is false + uint16_t ttiBundling; + /// default value is release + struct DRX_Config *drx_config; + /// default value is release + struct MAC_MainConfig__phr_Config *phr_config; + ///timer before triggering a periodic PHR + uint16_t periodicPHR_Timer; + ///timer before triggering a prohibit PHR + uint16_t prohibitPHR_Timer; + ///DL Pathloss change value + uint16_t PathlossChange; + ///number of subframe before triggering a periodic PHR + int16_t periodicPHR_SF; + ///number of subframe before triggering a prohibit PHR + int16_t prohibitPHR_SF; + ///DL Pathloss Change in db + uint16_t PathlossChange_db; + + /// default value is false + uint16_t extendedBSR_Sizes_r10; + /// default value is false + uint16_t extendedPHR_r10; + + //Bj bucket usage per lcid + int16_t Bj[MAX_NUM_LCID]; + // Bucket size per lcid + int16_t bucket_size[MAX_NUM_LCID]; +} NR_UE_SCHEDULING_INFO; + /*!\brief Top level UE MAC structure */ typedef struct { @@ -82,6 +169,7 @@ typedef struct { /// Random access parameter uint16_t ra_rnti; + uint16_t crnti; //BWP params NR_BWP_PARMS initial_bwp_dl; @@ -96,6 +184,13 @@ typedef struct { nr_ue_if_module_t *if_module; nr_scheduled_response_t scheduled_response; nr_phy_config_t phy_config; + + /// BSR report flag management + uint8_t BSR_reporting_active; + NR_UE_SCHEDULING_INFO scheduling_info; + + /// PHR + uint8_t PHR_reporting_active; } NR_UE_MAC_INST_t; typedef enum seach_space_mask_e { diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index c33d6244693f04868dd9cf39834b6db83a628688..9ddb47601d87aec8b6b4b162317ded524e870f9c 100755 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -140,5 +140,14 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, uint8_t eNB_index, uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode); +unsigned char +nr_generate_ulsch_pdu(uint8_t *mac_pdu, + uint8_t *sdus_payload, + uint8_t num_sdus, + uint16_t *sdu_lengths, + uint8_t *sdu_lcids, + uint16_t *crnti, + uint16_t buflen); + #endif /** @}*/ diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 4b966fd7b1abbee331f509ea8fa12be35b2112d9..ceff5baaa723f71e36480d0d7c80b4156e315395 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2319,282 +2319,63 @@ unsigned char *nr_parse_header(unsigned char *mac_header, } unsigned char -nr_generate_ulsch_header(uint8_t *mac_header, +nr_generate_ulsch_pdu(uint8_t *mac_pdu, + uint8_t *sdus_payload, uint8_t num_sdus, - uint8_t short_padding, uint16_t *sdu_lengths, uint8_t *sdu_lcids, - POWER_HEADROOM_CMD *power_headroom, uint16_t *crnti, - BSR_SHORT *truncated_bsr, - BSR_SHORT *short_bsr, - BSR_LONG *long_bsr, unsigned short post_padding) { - SCH_SUBHEADER_FIXED *mac_header_ptr = - (SCH_SUBHEADER_FIXED *) mac_header; - unsigned char first_element = 0, last_size = 0, i; - unsigned char mac_header_control_elements[16], *ce_ptr; - LOG_D(MAC, "[UE] Generate ULSCH : num_sdus %d\n", num_sdus); -#ifdef DEBUG_HEADER_PARSING - - for (i = 0; i < num_sdus; i++) { - LOG_T(MAC, "[UE] sdu %d : lcid %d length %d", i, sdu_lcids[i], - sdu_lengths[i]); - } - - LOG_T(MAC, "\n"); -#endif - ce_ptr = &mac_header_control_elements[0]; - - if ((short_padding == 1) || (short_padding == 2)) { - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = SHORT_PADDING; - first_element = 1; - last_size = 1; - } - - if (short_padding == 2) { - mac_header_ptr->E = 1; - mac_header_ptr++; - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = SHORT_PADDING; - last_size = 1; - } - - if (power_headroom) { - if (first_element > 0) { - mac_header_ptr->E = 1; - mac_header_ptr++; - } else { - first_element = 1; - } - - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = POWER_HEADROOM; - last_size = 1; - *((POWER_HEADROOM_CMD *) ce_ptr) = (*power_headroom); - ce_ptr += sizeof(POWER_HEADROOM_CMD); - LOG_D(MAC, "phr header size %zu\n", sizeof(POWER_HEADROOM_CMD)); - } - - if (crnti) { -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] CRNTI : %x (first_element %d)\n", *crnti, - first_element); -#endif - - if (first_element > 0) { - mac_header_ptr->E = 1; - mac_header_ptr++; - } else { - first_element = 1; - } - - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = CRNTI; - last_size = 1; - *((uint16_t *) ce_ptr) = (*crnti); - ce_ptr += sizeof(uint16_t); - // printf("offset %d\n",ce_ptr-mac_header_control_elements); - } - - if (truncated_bsr) { - if (first_element > 0) { - mac_header_ptr->E = 1; - /* - printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); - */ - mac_header_ptr++; - } else { - first_element = 1; - } - -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] Scheduler Truncated BSR Header\n"); -#endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = TRUNCATED_BSR; - last_size = 1; - *((BSR_TRUNCATED *) ce_ptr) = (*truncated_bsr); - ce_ptr += sizeof(BSR_TRUNCATED); - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - } else if (short_bsr) { - if (first_element > 0) { - mac_header_ptr->E = 1; - /* - printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); - */ - mac_header_ptr++; - } else { - first_element = 1; - } - -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] Scheduler SHORT BSR Header\n"); -#endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = SHORT_BSR; - last_size = 1; - *((BSR_SHORT *) ce_ptr) = (*short_bsr); - ce_ptr += sizeof(BSR_SHORT); - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - } else if (long_bsr) { - if (first_element > 0) { - mac_header_ptr->E = 1; - /* - printf("last subheader : %x (R%d,E%d,LCID%d)\n",*(unsigned char*)mac_header_ptr, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->R, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E, - ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID); - */ - mac_header_ptr++; - } else { - first_element = 1; - } + uint16_t buflen) { + + NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu; + unsigned char * ulsch_buffer_ptr = sdus_payload; + uint8_t last_size=0; + uint16_t sdu_length_total; + int i; + int offset=0; + + // 2) Generation of ULSCH MAC SDU subheaders + for (i = 0; i < num_sdus; i++) { + LOG_D(MAC, "[gNB] Generate ULSCH header num sdu %d len sdu %d\n", num_sdus, sdu_lengths[i]); + + if (sdu_lengths[i] < 128) { + ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0; + ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0; + ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i]; + ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->L = (unsigned char) sdu_lengths[i]; + last_size = 2; + } else { + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0; + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1; + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i]; + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f; + ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff; + last_size = 3; + } -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] Scheduler Long BSR Header\n"); -#endif - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = LONG_BSR; - last_size = 1; - *(ce_ptr) = - (long_bsr-> - Buffer_size0 << 2) | ((long_bsr->Buffer_size1 & 0x30) >> 4); - *(ce_ptr + 1) = - ((long_bsr->Buffer_size1 & 0x0F) << 4) | ((long_bsr-> - Buffer_size2 & 0x3C) - >> 2); - *(ce_ptr + 2) = - ((long_bsr-> - Buffer_size2 & 0x03) << 2) | (long_bsr->Buffer_size3 & 0x3F); - ce_ptr += BSR_LONG_SIZE; - // printf("(cont_res) : offset %d\n",ce_ptr-mac_header_control_elements); - } + mac_pdu_ptr += last_size; - // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); + // 3) cycle through SDUs, compute each relevant and place dlsch_buffer in + memcpy((void *) mac_pdu_ptr, (void *) ulsch_buffer_ptr, sdu_lengths[i]); + ulsch_buffer_ptr+= sdu_lengths[i]; + mac_pdu_ptr += sdu_lengths[i]; + } - for (i = 0; i < num_sdus; i++) { -#ifdef DEBUG_HEADER_PARSING - LOG_T(MAC, "[UE] sdu subheader %d (lcid %d, %d bytes)\n", i, - sdu_lcids[i], sdu_lengths[i]); -#endif + // 4) Compute final offset for padding + uint16_t padding_bytes = buflen - sdu_length_total; + if (padding_bytes > 0) { + ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0; + ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = UL_SCH_LCID_PADDING; + mac_pdu_ptr++; - if ((i == (num_sdus - 1)) - && ((short_padding) || (post_padding == 0))) { - if (first_element > 0) { - mac_header_ptr->E = 1; -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] last subheader : %x (R%d,E%d,LCID%d)\n", - *(unsigned char *) mac_header_ptr, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->R, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->E, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->LCID); -#endif - mac_header_ptr += last_size; - } + } else { + // no MAC subPDU with padding + } - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = sdu_lcids[i]; - } else { - if ((first_element > 0)) { - mac_header_ptr->E = 1; -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] last subheader : %x (R%d,E%d,LCID%d)\n", - *(unsigned char *) mac_header_ptr, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->R, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->E, - ((SCH_SUBHEADER_FIXED *) mac_header_ptr)->LCID); -#endif - mac_header_ptr += last_size; - // printf("last_size %d,mac_header_ptr %p\n",last_size,mac_header_ptr); - } else { - first_element = 1; - } + offset = ((unsigned char *) mac_pdu_ptr - mac_pdu); - if (sdu_lengths[i] < 128) { - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->R = 0; // 3 - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->E = 0; - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F = 0; - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->LCID = - sdu_lcids[i]; - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L = - (unsigned char) sdu_lengths[i]; - last_size = 2; -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] short sdu\n"); - LOG_T(MAC, - "[UE] last subheader : %x (R%d,E%d,LCID%d,F%d,L%d)\n", - ((uint16_t *) mac_header_ptr)[0], - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->R, - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->E, - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->LCID, - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->F, - ((SCH_SUBHEADER_SHORT *) mac_header_ptr)->L); -#endif - } else { - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->R = 0; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->E = 0; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->F = 1; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->LCID = - sdu_lcids[i]; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_MSB = - ((unsigned short) sdu_lengths[i] >> 8) & 0x7f; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->L_LSB = - (unsigned short) sdu_lengths[i] & 0xff; - ((SCH_SUBHEADER_LONG *) mac_header_ptr)->padding = 0x00; - last_size = 3; -#ifdef DEBUG_HEADER_PARSING - LOG_D(MAC, "[UE] long sdu\n"); -#endif - } - } - } - - if (post_padding > 0) { // we have lots of padding at the end of the packet - mac_header_ptr->E = 1; - mac_header_ptr += last_size; - // add a padding element - mac_header_ptr->R = 0; - mac_header_ptr->E = 0; - mac_header_ptr->LCID = SHORT_PADDING; - mac_header_ptr++; - } else { // no end of packet padding - // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE) - mac_header_ptr++; - //mac_header_ptr=last_size; // FIXME: should be ++ - } - if ((ce_ptr - mac_header_control_elements) > 0) { - memcpy((void *) mac_header_ptr, mac_header_control_elements, - ce_ptr - mac_header_control_elements); - mac_header_ptr += - (unsigned char) (ce_ptr - mac_header_control_elements); - } - -#ifdef DEBUG_HEADER_PARSING - LOG_T(MAC, " [UE] header : "); - - for (i = 0; i < ((unsigned char *) mac_header_ptr - mac_header); i++) { - LOG_T(MAC, "%2x.", mac_header[i]); - } - - LOG_T(MAC, "\n"); -#endif - return ((unsigned char *) mac_header_ptr - mac_header); + return offset; } @@ -2694,93 +2475,68 @@ nr_ue_send_sdu(module_id_t module_idP, } -/* LTE based function to be substituted once NR version is ready */ + uint8_t nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, uint8_t eNB_index, - uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) - -{ + uint8_t *ulsch_buffer, uint16_t buflen, uint8_t *access_mode) { uint8_t total_rlc_pdu_header_len = 0, rlc_pdu_header_len_last = 0; uint16_t buflen_remain = 0; - uint8_t bsr_len = 0, bsr_ce_len = 0, bsr_header_len = 0; - uint8_t phr_header_len = 0, phr_ce_len = 0, phr_len = 0; - uint8_t lcid = 0, lcid_rlc_pdu_count = 0; - boolean_t is_lcid_processed = FALSE; - boolean_t is_all_lcid_processed = FALSE; + uint8_t lcid = 0; uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t payload_offset = 0, num_sdus = 0; - uint8_t ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES]; + uint8_t ulsch_sdus[MAX_ULSCH_PAYLOAD_BYTES]; uint16_t sdu_length_total = 0; - BSR_SHORT bsr_short, bsr_truncated; - BSR_LONG bsr_long; - BSR_SHORT *bsr_s = &bsr_short; - BSR_LONG *bsr_l = &bsr_long; - BSR_SHORT *bsr_t = &bsr_truncated; - POWER_HEADROOM_CMD phr; - POWER_HEADROOM_CMD *phr_p = &phr; - unsigned short short_padding = 0, post_padding = 0, padding_len = 0; + unsigned short post_padding = 0, padding_len = 0; int j; // used for padding - // Compute header length - int lcg_id = 0; - int lcg_id_bsr_trunc = 0; - int highest_priority = 16; - int num_lcg_id_with_data = 0; + rlc_buffer_occupancy_t lcid_buffer_occupancy_old = 0, lcid_buffer_occupancy_new = 0; - - NR_UE_MAC_INST_t *nr_ue_mac_inst = get_mac_inst(0); - - LOG_D(MAC, "[UE %d] MAC PROCESS UL TRANSPORT BLOCK at frame%d subframe %d TBS=%d\n", module_idP, frameP, subframe, buflen); AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n"); +#if UE_TIMING_TRACE + start_meas(&UE_mac_inst[module_idP].tx_ulsch_sdu); +#endif - bsr_header_len = 0; - phr_header_len = 0; // 1; //sizeof(SCH_SUBHEADER_FIXED); - - rlc_buffer_occupancy_t buffer_occupancy = mac_rlc_get_buffer_occupancy_ind( module_idP, 0x1234, eNB_index, frameP, subframe,ENB_FLAG_NO,DTCH); + NR_UE_MAC_INST_t *nr_ue_mac_inst = get_mac_inst(0); // Check for DCCH first // TO DO: Multiplex in the order defined by the logical channel prioritization - for (lcid = DTCH; - (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE); lcid++) { - lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind( module_idP, 0x1234, eNB_index, frameP, subframe,ENB_FLAG_NO,lcid); - if (lcid_buffer_occupancy_old > 0) { - lcid_rlc_pdu_count = 0; - is_lcid_processed = FALSE; - + for (lcid = DCCH; + lcid < MAX_NUM_LCID; lcid++) { + + lcid_buffer_occupancy_old = + //TODO: Replace static value with CRNTI + mac_rlc_get_buffer_occupancy_ind(module_idP, + 0x1234, eNB_index, frameP, //nr_ue_mac_inst->crnti + subframe, ENB_FLAG_NO, + lcid); lcid_buffer_occupancy_new = lcid_buffer_occupancy_old; - - //Multiplex all available DCCH RLC PDUs considering to multiplex the last PDU each time for maximize the data - //Adjust at the end of the loop - while ((!is_lcid_processed) && (lcid_buffer_occupancy_new) - && (bsr_len + phr_len + total_rlc_pdu_header_len + - sdu_length_total + MIN_MAC_HDR_RLC_SIZE <= buflen)) { + if(lcid_buffer_occupancy_new){ buflen_remain = - buflen - (bsr_len + phr_len + - total_rlc_pdu_header_len + sdu_length_total + - 1); - LOG_I(MAC, + buflen - (total_rlc_pdu_header_len + sdu_length_total + MIN_MAC_HDR_RLC_SIZE); + LOG_D(MAC, "[UE %d] Frame %d : UL-DXCH -> ULSCH, RLC %d has %d bytes to " - "send (Transport Block size %d BSR size=%d PHR=%d SDU Length Total %d , mac header len %d BSR byte before Tx=%d)\n", + "send (Transport Block size %d SDU Length Total %d , mac header len %d )\n", //BSR byte before Tx=%d module_idP, frameP, lcid, lcid_buffer_occupancy_new, - buflen, bsr_len, phr_len, sdu_length_total, - total_rlc_pdu_header_len); + buflen, sdu_length_total, + total_rlc_pdu_header_len); // ,nr_ue_mac_inst->scheduling_info.BSR_bytes[nr_ue_mac_inst->scheduling_info.LCGID[lcid]] + //TODO: Replace static value with CRNTI sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - 0x1234, eNB_index, + 0x1234, eNB_index, //nr_ue_mac_inst->crnti frameP, ENB_FLAG_NO, MBMS_FLAG_NO, lcid, buflen_remain, - (char *)&ulsch_buff[sdu_length_total],0, + (char *)&ulsch_sdus[sdu_length_total],0, 0 ); AssertFatal(buflen_remain >= sdu_lengths[num_sdus], @@ -2790,247 +2546,58 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, if (sdu_lengths[num_sdus]) { sdu_length_total += sdu_lengths[num_sdus]; sdu_lcids[num_sdus] = lcid; - LOG_I(MAC, - "[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n", - module_idP, sdu_lengths[num_sdus], lcid); - - if (buflen == - (bsr_len + phr_len + total_rlc_pdu_header_len + - sdu_length_total + 1)) { - //No more remaining TBS after this PDU - //exit the function - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; - } else { - rlc_pdu_header_len_last = - (sdu_lengths[num_sdus] > 128) ? 3 : 2; - - //Change to 1 byte if it does not fit in the TBS, ie last PDU - if (buflen <= - (bsr_len + phr_len + total_rlc_pdu_header_len + - rlc_pdu_header_len_last + sdu_length_total)) { - rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; - } - } + //LOG_I(MAC, + // "[UE %d] TX Multiplex RLC PDU TX Got %d bytes for LcId%d\n", + // module_idP, sdu_lengths[num_sdus], lcid); //Update number of SDU num_sdus++; //Update total MAC Header size for RLC PDUs and save last one total_rlc_pdu_header_len += rlc_pdu_header_len_last; - lcid_rlc_pdu_count++; - } else { - /* avoid infinite loop ... */ - is_lcid_processed = TRUE; } /* Get updated BO after multiplexing this PDU */ - lcid_buffer_occupancy_new = - mac_rlc_get_buffer_occupancy_ind( module_idP, - 0x1234, - eNB_index, - frameP, - subframe, - ENB_FLAG_NO, - lcid); + //TODO: Replace static value with CRNTI + + /*lcid_buffer_occupancy_new = + mac_rlc_get_buffer_occupancy_ind(module_idP, + 0x1234, //nr_ue_mac_inst->crnti + eNB_index, frameP, + subframe, ENB_FLAG_NO, + lcid); is_lcid_processed = (is_lcid_processed) - || (lcid_buffer_occupancy_new <= 0); - } - - //Update Buffer remain and BSR bytes after transmission - AssertFatal(lcid_buffer_occupancy_new <= - lcid_buffer_occupancy_old, - "MAC UE Tx error : Buffer Occupancy After Tx=%d greater than before=%d BO! for LCID=%d RLC PDU nb=%d Frame %d Subrame %d\n", - lcid_buffer_occupancy_new, - lcid_buffer_occupancy_old, lcid, - lcid_rlc_pdu_count, frameP, subframe); - } - } - - - // build PHR and update the timers - /*if (phr_ce_len == sizeof(POWER_HEADROOM_CMD)) { - if(NFAPI_MODE==NFAPI_UE_STUB_PNF) { - //Substitute with a static value for the MAC layer abstraction (phy_stub mode) - phr_p->PH = 40; - } else { - phr_p->PH = get_phr_mapping(module_idP, CC_id, eNB_index); - } - - phr_p->R = 0; - LOG_D(MAC, - "[UE %d] Frame %d report PHR with mapping (%d->%d) for LCID %d\n", - module_idP, frameP, get_PHR(module_idP, CC_id, eNB_index), - phr_p->PH, POWER_HEADROOM); - update_phr(module_idP, CC_id); - } else { - phr_p = NULL; - }*/ - - - // Check BSR padding: it is done after PHR according to Logical Channel Prioritization order - // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 - /* For Padding BSR: - - if the number of padding bits is equal to or larger than the size of the Short BSR plus its subheader but smaller than the size of the Long BSR plus its subheader: - - if more than one LCG has data available for transmission in the TTI where the BSR is transmitted: report Truncated BSR of the LCG with the highest priority logical channel with data available for transmission; - - else report Short BSR. - - else if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR. - */ - if (sdu_length_total) { - padding_len = - buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - - rlc_pdu_header_len_last + sdu_length_total + 1); - } else { - padding_len = buflen - (bsr_len + phr_len); - } - - /* if ((padding_len) && (bsr_len == 0)) { - // if the number of padding bits is equal to or larger than the size of the Long BSR plus its subheader, report Long BSR - if (padding_len >= (1 + BSR_LONG_SIZE)) { - bsr_ce_len = BSR_LONG_SIZE; - bsr_header_len = 1; - // Trigger BSR Padding - UE_mac_inst[module_idP].BSR_reporting_active |= - BSR_TRIGGER_PADDING; - } else if (padding_len >= (1 + sizeof(BSR_SHORT))) { - bsr_ce_len = sizeof(BSR_SHORT); - bsr_header_len = 1; - - if (num_lcg_id_with_data > 1) { - // REPORT TRUNCATED BSR - //Get LCGID of highest priority LCID with data - for (lcid = DCCH; lcid < MAX_NUM_LCID; lcid++) { - if (UE_mac_inst[module_idP]. - logicalChannelConfig[lcid] != NULL) { - lcg_id = - UE_mac_inst[module_idP].scheduling_info. - LCGID[lcid]; - - if ((lcg_id < MAX_NUM_LCGID) - && (UE_mac_inst[module_idP]. - scheduling_info.BSR_bytes[lcg_id]) - && - (UE_mac_inst[module_idP].logicalChannelConfig - [lcid]->ul_SpecificParameters->priority <= - highest_priority)) { - highest_priority = - UE_mac_inst[module_idP]. - logicalChannelConfig[lcid]-> - ul_SpecificParameters->priority; - lcg_id_bsr_trunc = lcg_id; - } - } - } - } else { - //Report SHORT BSR, clear bsr_t - bsr_t = NULL; - } - - // Trigger BSR Padding - UE_mac_inst[module_idP].BSR_reporting_active |= - BSR_TRIGGER_PADDING; - } - - bsr_len = bsr_header_len + bsr_ce_len; - }*/ - - //Fill BSR Infos - if (bsr_ce_len == 0) { - bsr_s = NULL; - bsr_l = NULL; - bsr_t = NULL; - } - else { - LOG_W(MAC, "BSR not null \n"); - } - - // 1-bit padding or 2-bit padding special padding subheader - // Check for max padding size, ie MAC Hdr for last RLC PDU = 1 - if (sdu_length_total) { - padding_len = - buflen - (bsr_len + phr_len + total_rlc_pdu_header_len - - rlc_pdu_header_len_last + sdu_length_total + 1); - } else { - padding_len = buflen - (bsr_len + phr_len); - } - - if (padding_len <= 2) { - short_padding = padding_len; - // only add padding header - post_padding = 0; - - //update total MAC Hdr size for RLC data - if (sdu_length_total) { - total_rlc_pdu_header_len = - total_rlc_pdu_header_len - rlc_pdu_header_len_last + 1; - rlc_pdu_header_len_last = 1; - } - } else if (sdu_length_total) { - post_padding = - buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + - sdu_length_total + 1); - - // If by adding MAC Hdr for last RLC PDU the padding is 0 then set MAC Hdr for last RLC PDU = 1 and compute 1 or 2 byte padding - if (post_padding == 0) { - total_rlc_pdu_header_len -= rlc_pdu_header_len_last; - padding_len = - buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + - sdu_length_total + 1); - short_padding = padding_len; - total_rlc_pdu_header_len++; - } - } else { - if (padding_len == buflen) { // nona mac pdu - *access_mode = CANCELED_ACCESS; - } - - short_padding = 0; - post_padding = - buflen - (bsr_len + phr_len + total_rlc_pdu_header_len + - sdu_length_total + 1); + || (lcid_buffer_occupancy_new <= 0);*/ } - // Generate header - // if (num_sdus>0) { +} - // cycle through SDUs and place in ulsch_buffer - if (sdu_length_total) { - payload_offset = nr_generate_ulsch_header(ulsch_buffer, // mac header + // Generate ULSCH PDU + if (num_sdus>0) { + payload_offset = nr_generate_ulsch_pdu(ulsch_buffer, // mac header + ulsch_sdus, num_sdus, // num sdus - short_padding, // short pading sdu_lengths, // sdu length sdu_lcids, // sdu lcid - phr_p, // power headroom NULL, // crnti - bsr_t, // truncated bsr - bsr_s, // short bsr - bsr_l, post_padding); // long_bsr + buflen); // long_bsr + } + else + return 0; LOG_D(MAC, - "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, padding %d,post_padding %d, bsr len %d, phr len %d, reminder %d \n", + "[UE %d] Generate header :bufflen %d sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d, total_rlc_pdu_header_len %d, post_padding %d, remainder %d \n", module_idP, buflen, sdu_length_total, num_sdus, sdu_lengths[0], sdu_lcids[0], payload_offset, total_rlc_pdu_header_len, - short_padding, post_padding, bsr_len, phr_len, - buflen - sdu_length_total - payload_offset); + post_padding, buflen - sdu_length_total - payload_offset); - - memcpy(&ulsch_buffer[payload_offset], ulsch_buff, - sdu_length_total); + // Padding: fill remainder of ULSCH with 0 + if (buflen - payload_offset > 0){ + for (int j = 0; j < (buflen - payload_offset); j++) + ulsch_buffer[payload_offset + j] = 0; } - else - return 0; - // fill remainder of DLSCH with random data - if (post_padding) { - for (j = 0; j < (buflen - sdu_length_total - payload_offset); j++) { - ulsch_buffer[payload_offset + sdu_length_total + j] = - (char) (taus() & 0xff); - } - } #if defined(ENABLE_MAC_PAYLOAD_DEBUG) - LOG_D(MAC, "Printing UL MAC payload without the header UE side: \n"); - for (int i = payload_offset; i < sdu_length_total ; i++) { + LOG_I(MAC, "Printing UL MAC payload without the header UE side, payload_offset: %d \n", payload_offset); + for (int i = 0; i < sdu_length_total ; i++) { //harq_process_ul_ue->a[i] = (unsigned char) rand(); //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]); printf("%02x ",(unsigned char)ulsch_buffer[i]); @@ -3039,9 +2606,4 @@ nr_ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, #endif return 1; - } - - - - diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 1615a8e68768e6f819444647c74e3466e3bfb88c..a041f7cce387dc862cdbc5fb0875cd9d95a7a854 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -34,6 +34,7 @@ #include "PHY/NR_TRANSPORT/nr_dlsch.h" #include "PHY/NR_TRANSPORT/nr_dci.h" #include "executables/nr-softmodem.h" +#include "LAYER2/NR_MAC_COMMON/nr_mac.h" extern RAN_CONTEXT_t RC; //#define ENABLE_MAC_PAYLOAD_DEBUG 1 @@ -549,7 +550,185 @@ void nr_schedule_uss_ulsch_phytest(nfapi_nr_ul_tti_request_t *UL_tti_req, } } -void +void nr_process_mac_pdu( + module_id_t module_idP, + uint8_t CC_id, + frame_t frameP, + uint8_t *pduP, + uint16_t mac_pdu_len) +{ + + // This function is adapting code from the old + // parse_header(...) and ue_send_sdu(...) functions of OAI LTE + + uint8_t *pdu_ptr = pduP, rx_lcid, done = 0, i; + int pdu_len = mac_pdu_len; + uint16_t mac_ce_len, mac_subheader_len, mac_sdu_len; + + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; + + LOG_I(MAC, "LCID received at gNB side: %d \n", rx_lcid); + + // For both DL/UL-SCH + // Except: + // - UL/DL-SCH: fixed-size MAC CE(known by LCID) + // - UL/DL-SCH: padding + // - UL-SCH: MSG3 48-bits + // |0|1|2|3|4|5|6|7| bit-wise + // |R|F| LCID | + // | L | + // |0|1|2|3|4|5|6|7| bit-wise + // |R|F| LCID | + // | L | + // | L | + + // For both DL/UL-SCH + // For: + // - UL/DL-SCH: fixed-size MAC CE(known by LCID) + // - UL/DL-SCH: padding, for single/multiple 1-oct padding CE(s) + // - UL-SCH: MSG3 48-bits + // |0|1|2|3|4|5|6|7| bit-wise + // |R|R| LCID | + // LCID: The Logical Channel ID field identifies the logical channel instance of the corresponding MAC SDU or the type of the corresponding MAC CE or padding as described in Tables 6.2.1-1 and 6.2.1-2 for the DL-SCH and UL-SCH respectively. There is one LCID field per MAC subheader. The LCID field size is 6 bits; + // L: The Length field indicates the length of the corresponding MAC SDU or variable-sized MAC CE in bytes. There is one L field per MAC subheader except for subheaders corresponding to fixed-sized MAC CEs and padding. The size of the L field is indicated by the F field; + // F: lenght of L is 0:8 or 1:16 bits wide + // R: Reserved bit, set to zero. + + while (!done && pdu_len > 0){ + mac_ce_len = 0; + mac_subheader_len = 1; // default to fixed-length subheader = 1-oct + mac_sdu_len = 0; + rx_lcid = ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID; + + LOG_I(MAC, "LCID received at gNB side: %d \n", rx_lcid); + + switch(rx_lcid){ + // MAC CE + + /*#ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE] LCID %d, PDU length %d\n", ((NR_MAC_SUBHEADER_FIXED *)pdu_ptr)->LCID, pdu_len); + #endif*/ + + case UL_SCH_LCID_PADDING: + done = 1; + // end of MAC PDU, can ignore the rest. + break; + + case UL_SCH_LCID_DTCH: + // check if LCID is valid at current time. + if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){ + //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8; + mac_subheader_len = 3; + mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8) + | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff); + + } else { + mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L; + mac_subheader_len = 2; + } + + LOG_D(MAC, "[UE %d] Frame %d : DLSCH -> DL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len); + + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) + LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); + + for (i = 0; i < 32; i++) + LOG_T(MAC, "%x.", (pdu_ptr + mac_subheader_len)[i]); + + LOG_T(MAC, "\n"); + #endif + + if (IS_SOFTMODEM_NOS1){ + if (rx_lcid < NB_RB_MAX && rx_lcid >= UL_SCH_LCID_DTCH) { + + mac_rlc_data_ind(module_idP, + 0x1234, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcid, + (char *) (pdu_ptr + mac_subheader_len), + mac_sdu_len, + 1, + NULL); + } else { + LOG_E(MAC, "[UE %d] Frame %d : unknown LCID %d (gNB %d)\n", module_idP, frameP, rx_lcid, module_idP); + } + } + + break; + + default: + return; + break; + } + pdu_ptr += ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + pdu_len -= ( mac_subheader_len + mac_ce_len + mac_sdu_len ); + + AssertFatal(pdu_len >= 0, "[MAC] nr_process_mac_pdu, residual mac pdu length < 0!\n"); + } +} + +void nr_rx_sdu(module_id_t module_idP, + uint8_t CC_id, + frame_t frameP, + uint8_t ttiP, + const rnti_t rntiP, + uint8_t * pdu, + const uint16_t pdu_len, + const uint16_t timing_advance, + const uint8_t ul_cqi) +{ + + LOG_I(MAC, "Handling PDU frame %d slot %d pdu_len: %d \n", frameP, ttiP, pdu_len); + + uint8_t * pduP = pdu; + + + /*if (opt_enabled) { + trace_pdu(DIRECTION_DOWNLINK, pduP, pdu_len, module_idP, WS_C_RNTI, + UE_mac_inst[module_idP].cs_RNTI, frameP, ttiP, 0, 0); //subframeP + LOG_D(OPT, "[UE %d][DLSCH] Frame %d trace pdu for rnti %x with size %d\n", + module_idP, frameP, UE_mac_inst[module_idP].cs_RNTI, pdu_len); + }*/ + + /* + #ifdef DEBUG_HEADER_PARSING + LOG_D(MAC, "[UE %d] ue_send_sdu : Frame %d gNB_index %d : num_ce %d num_sdu %d\n", + module_idP, frameP, gNB_index, num_ce, num_sdu); + #endif + */ + + /* + #if defined(ENABLE_MAC_PAYLOAD_DEBUG) + LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP); + for (i = 0; i < 32; i++) { + LOG_T(MAC, "%x.", sdu[i]); + } + LOG_T(MAC, "\n"); + #endif + */ + + // Processing MAC PDU + // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs + if (pduP != NULL){ + LOG_I(MAC, "Received PDU at MAC gNB \n"); + nr_process_mac_pdu(module_idP, CC_id, frameP, pduP, pdu_len); + } + + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT); + + /* + #if UE_TIMING_TRACE + stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu); + #endif + */ +} + + +/* LTE based function to be substituted once NR version is ready */ +/*void nr_rx_sdu(const module_id_t enb_mod_idP, const int CC_idP, const frame_t frameP, @@ -582,7 +761,7 @@ nr_rx_sdu(const module_id_t enb_mod_idP, rrc_eNB_ue_context_t *ue_contextP = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; UE_TEMPLATE *UE_template_ptr = NULL; - /* Init */ + // Init current_rnti = rntiP; UE_id = 0; //find_UE_id(enb_mod_idP, current_rnti); //mac = RC.mac[enb_mod_idP]; @@ -604,7 +783,7 @@ nr_rx_sdu(const module_id_t enb_mod_idP, return; } - /* Control element */ + // Control element for (int i = 0; i < num_ce; i++) { switch (rx_ces[i]) { // implement and process PHR + CRNTI + BSR @@ -690,7 +869,7 @@ nr_rx_sdu(const module_id_t enb_mod_idP, rx_lcids[i]); if (UE_id != -1) { - /* Adjust buffer occupancy of the correponding logical channel group */ + // Adjust buffer occupancy of the correponding logical channel group LOG_D(MAC, "[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d \n", enb_mod_idP, CC_idP, @@ -709,14 +888,15 @@ nr_rx_sdu(const module_id_t enb_mod_idP, pritnf("\n"); #endif mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr+1, rx_lengths[i], 1, NULL); - } else { /* rx_length[i] Max size */ + } else { // rx_length[i] Max size //UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; - LOG_E(MAC, "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", + LOG_E(MAC, "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d. Size of received payload: %d \n", enb_mod_idP, CC_idP, frameP, rx_lcids[i], - UE_id); + UE_id, + rx_lengths[i]); } } else { // end if (UE_id != -1) LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ", @@ -734,32 +914,5 @@ nr_rx_sdu(const module_id_t enb_mod_idP, payload_ptr += rx_lengths[i]; } - /* Program ACK for PHICH */ - - /*LOG_D(MAC, "Programming PHICH ACK for rnti %x harq_pid %d (first_rb %d)\n", - current_rnti, - harq_pid, - first_rb); - nfapi_hi_dci0_request_t *hi_dci0_req; - uint8_t sf_ahead_dl = ul_subframe2_k_phich(&mac->common_channels[CC_idP], subframeP); - hi_dci0_req = &mac->HI_DCI0_req[CC_idP][(subframeP+sf_ahead_dl)%10]; - nfapi_hi_dci0_request_body_t *hi_dci0_req_body = &hi_dci0_req->hi_dci0_request_body; - nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + - hi_dci0_req_body->number_of_hi]; - memset((void *) hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_HI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_hi_pdu); - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start = first_rb; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms = 0; - hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value = 1; - hi_dci0_req_body->number_of_hi++; - hi_dci0_req_body->sfnsf = sfnsf_add_subframe(frameP,subframeP, 0); - hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; - hi_dci0_req->sfn_sf = sfnsf_add_subframe(frameP,subframeP, sf_ahead_dl); - hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;*/ - - /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */ - -} +}*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 95abba549ab3756b0ee948fe2fc5b3eaca8d5ee9..77d6053a35bb806a611d5bb9ccaa8b85c4316e1a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -145,15 +145,21 @@ void config_nr_mib(int Mod_idP, int cellBarred, int intraFreqReselection); -void -nr_rx_sdu(const module_id_t enb_mod_idP, - const int CC_idP, - const frame_t frameP, - const sub_frame_t subframeP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const uint16_t timing_advance, - const uint8_t ul_cqi); +void nr_rx_sdu(module_id_t module_idP, + uint8_t CC_id, + frame_t frameP, + uint8_t ttiP, + const rnti_t rntiP, + uint8_t * pdu, + uint16_t pdu_len, + const uint16_t timing_advance, + const uint8_t ul_cqi); + +void nr_process_mac_pdu( + module_id_t module_idP, + uint8_t CC_id, + frame_t frameP, + uint8_t *pduP, + uint16_t mac_pdu_len); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2094b3517e40e3c887542227ecc430b262f90669..6a6dc746951c8cb6bd44dbbd1be7cf5699f0483f 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -192,7 +192,7 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) { UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance, UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi); } else { - LOG_D(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->slot); + LOG_I(MAC,"Frame %d, Slot %d Calling rx_sdu (CRC ok), received length: %d \n",UL_info->frame,UL_info->slot, UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length); nr_rx_sdu(UL_info->module_id, UL_info->CC_id, NFAPI_SFNSF2SFN(UL_info->rx_ind.sfn_sf), //UL_info->frame,