Merge remote-tracking branch 'origin/develop' into benetel_phase_rotation

This commit is contained in:
Florian Kaltenberger
2020-11-09 13:58:41 +01:00
158 changed files with 9201 additions and 4150 deletions
-13
View File
@@ -65,18 +65,6 @@
#define MAX_NR_RRC_UE_CONTEXTS 64
#ifndef UE_EXPANSION
// TODO:L2 FAPI simulator.
// UESIM_EXPANSION is used to be same value of MAX_MOBILES_PER_ENB
// in eNB and UE.
// now , if we use --mu option in UE, compiling error will occur.
// This problem will be fixed in the future.
#ifdef UESIM_EXPANSION
#define MAX_MOBILES_PER_ENB 256
#define MAX_MOBILES_PER_ENB_NB_IoT 256
#define MAX_MOBILES_PER_GNB 256
#define MAX_eNB 2
#define MAX_gNB 2
#else
#ifdef LARGE_SCALE
#define MAX_MOBILES_PER_ENB 128
#define MAX_MOBILES_PER_ENB_NB_IoT 128
@@ -90,7 +78,6 @@
#define MAX_eNB 2
#define MAX_gNB 2
#endif
#endif
#else
#define MAX_MOBILES_PER_ENB 256
#define MAX_MOBILES_PER_ENB_NB_IoT 256
@@ -56,6 +56,8 @@
#include "flexran.pb-c.h"
#include "flexran_agent_mac.h"
#include <dlfcn.h>
#include <openair2/LAYER2/MAC/mac.h>
#include "T.h"
+57 -24
View File
@@ -947,6 +947,24 @@ int get_format0(uint8_t index,
return format;
}
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired) {
int64_t *prach_config_info_p;
if (pointa > 2016666) { //FR2
prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
}
else { // FR1
if (unpaired)
prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
else
prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
} // FR2 / FR1
return prach_config_info_p;
}
void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
uint16_t *slot_period,
uint16_t *offset) {
@@ -1451,7 +1469,7 @@ nr_bandentry_t nr_bandtable[] = {
{5, 824000, 849000, 869000, 894000, 20, 173800, 100},
{7, 2500000, 2570000, 2620000, 2690000, 20, 524000, 100},
{8, 880000, 915000, 925000, 960000, 20, 185000, 100},
{12, 698000, 716000, 728000, 746000, 20, 145800, 100},
{12, 698000, 716000, 729000, 746000, 20, 145800, 100},
{20, 832000, 862000, 791000, 821000, 20, 158200, 100},
{25, 1850000, 1915000, 1930000, 1995000, 20, 386000, 100},
{28, 703000, 758000, 758000, 813000, 20, 151600, 100},
@@ -1473,22 +1491,22 @@ nr_bandentry_t nr_bandtable[] = {
{77, 3300000, 4200000, 3300000, 4200000, 2, 620000, 30},
{78, 3300000, 3800000, 3300000, 3800000, 1, 620000, 15},
{78, 3300000, 3800000, 3300000, 3800000, 2, 620000, 30},
{79, 4400000, 5000000, 4400000, 5000000, 1, 693334, 15},
{79, 4400000, 5000000, 4400000, 5000000, 2, 693334, 30},
{79, 4400010, 5000000, 4400010, 5000000, 1, 693334, 15},
{79, 4400010, 5000000, 4400010, 5000000, 2, 693334, 30},
{80, 1710000, 1785000, 000, 000, 20, 342000, 100},
{81, 860000, 915000, 000, 000, 20, 176000, 100},
{81, 880000, 915000, 000, 000, 20, 176000, 100},
{82, 832000, 862000, 000, 000, 20, 166400, 100},
{83, 703000, 748000, 000, 000, 20, 140600, 100},
{84, 1920000, 1980000, 000, 000, 20, 384000, 100},
{86, 1710000, 1785000, 000, 000, 20, 342000, 100},
{257,26500000,29500000,26500000,29500000, 1,2054166, 60},
{257,26500000,29500000,26500000,29500000, 2,2054167, 120},
{258,24250000,27500000,24250000,27500000, 1,2016667, 60},
{258,24250000,27500000,24250000,27500000, 2,2016667, 120},
{260,37000000,40000000,37000000,40000000, 1,2229166, 60},
{260,37000000,40000000,37000000,40000000, 2,2229167, 120},
{261,27500000,28350000,27500000,28350000, 1,2070833, 60},
{261,27500000,28350000,27500000,28350000, 2,2070833, 120}
{257,26500020,29500000,26500020,29500000, 1,2054166, 60},
{257,26500080,29500000,26500080,29500000, 2,2054167, 120},
{258,24250080,27500000,24250080,27500000, 1,2016667, 60},
{258,24250080,27500000,24250080,27500000, 2,2016667, 120},
{260,37000020,40000000,37000020,40000000, 1,2229166, 60},
{260,37000080,40000000,37000080,40000000, 2,2229167, 120},
{261,27500040,28350000,27500040,28350000, 1,2070833, 60},
{261,27500040,28350000,27500040,28350000, 2,2070833, 120}
};
@@ -1718,13 +1736,23 @@ uint32_t to_nrarfcn(int nr_bandP,
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz));
int deltaFglobal = 60;
uint32_t N_REF_Offs = 2016667;
uint64_t F_REF_Offs_khz = 24250080;
if (dl_CarrierFreq < 3e9) deltaFglobal = 15;
if (dl_CarrierFreq < 24.25e9) deltaFglobal = 5;
if (dl_CarrierFreq < 24.25e9) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_CarrierFreq < 3e9) {
deltaFglobal = 5;
N_REF_Offs = 0;
F_REF_Offs_khz = 0;
}
// This is equation before Table 5.4.2.1-1 in 38101-1-f30
// F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs)
nrarfcn = (((dl_CarrierFreq_by_1k - nr_bandtable[i].dl_min)/deltaFglobal)+nr_bandtable[i].N_OFFs_DL);
nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs);
delta_arfcn = nrarfcn - nr_bandtable[i].N_OFFs_DL;
if(delta_arfcn%(nr_bandtable[i].step_size)!=0)
@@ -1741,13 +1769,21 @@ uint64_t from_nrarfcn(int nr_bandP,
{
int i;
int deltaFglobal = 5;
uint32_t N_REF_Offs = 0;
uint64_t F_REF_Offs_khz = 0;
int scs_khz = 15<<scs_index;
uint32_t delta_arfcn;
if (dl_nrarfcn > 599999 && dl_nrarfcn < 2016667)
deltaFglobal = 15;
if (dl_nrarfcn > 2016666 && dl_nrarfcn < 3279166)
if (dl_nrarfcn > 599999 && dl_nrarfcn < 2016667) {
deltaFglobal = 15;
N_REF_Offs = 600000;
F_REF_Offs_khz = 3000000;
}
if (dl_nrarfcn > 2016666 && dl_nrarfcn < 3279166) {
deltaFglobal = 60;
N_REF_Offs = 2016667;
F_REF_Offs_khz = 24250080;
}
AssertFatal(nr_bandP <= 261, "nr_band %d > 260\n", nr_bandP);
for (i = 0; i < NR_BANDTABLE_SIZE && nr_bandtable[i].band != nr_bandP; i++);
@@ -1761,14 +1797,11 @@ uint64_t from_nrarfcn(int nr_bandP,
if(delta_arfcn%(nr_bandtable[i].step_size)!=0)
AssertFatal(1==0,"dl_nrarfcn %u is not on the raster for step size %lu",dl_nrarfcn,nr_bandtable[i].step_size);
LOG_I(PHY,"Computing dl_frequency (pointA %llu => %llu (dlmin %llu, nr_bandtable[%d].N_OFFs_DL %llu))\n",
LOG_I(PHY,"Computing dl_frequency (arfcn %llu => %llu)\n",
(unsigned long long)dl_nrarfcn,
(unsigned long long)(1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal)),
(unsigned long long)nr_bandtable[i].dl_min,
i,
(unsigned long long)nr_bandtable[i].N_OFFs_DL);
(unsigned long long)(1000*(F_REF_Offs_khz + (dl_nrarfcn - N_REF_Offs) * deltaFglobal)));
return 1000*(nr_bandtable[i].dl_min + (dl_nrarfcn - nr_bandtable[i].N_OFFs_DL) * deltaFglobal);
return 1000*(F_REF_Offs_khz + (dl_nrarfcn - N_REF_Offs) * deltaFglobal);
}
@@ -36,6 +36,36 @@
#include "NR_CellGroupConfig.h"
#include "nr_mac.h"
// ===============================================
// SSB to RO mapping public defines and structures
// ===============================================
#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
// PRACH occasion details
typedef struct prach_occasion_info {
uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz)
uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern)
uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
uint8_t nb_mapped_ssb;
uint16_t format; // RO preamble format
} prach_occasion_info_t;
// PRACH occasion slot details
// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
typedef struct prach_occasion_slot {
prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot
uint8_t nb_of_prach_occasion_in_time;
uint8_t nb_of_prach_occasion_in_freq;
} prach_occasion_slot_t;
// ========================================
typedef enum {
NR_DL_DCI_FORMAT_1_0 = 0,
NR_DL_DCI_FORMAT_1_1,
@@ -133,6 +163,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco
int get_format0(uint8_t index, uint8_t unpaired);
int64_t *get_prach_config_info(uint32_t pointa,
uint8_t index,
uint8_t unpaired);
uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
int get_num_dmrs(uint16_t dmrs_mask );
+6 -3
View File
@@ -204,7 +204,7 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
uint16_t band;
int32_t offset;
get_band((cfg->carrier_config.dl_frequency)*1000,
get_band((uint64_t)(cfg->carrier_config.dl_frequency)*1000,
&band,
&offset,
&frame_type);
@@ -243,8 +243,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0;
cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0;
for (i=0; i<4; i++) {
cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
}
break;
default:
@@ -433,6 +433,9 @@ int nr_rrc_mac_config_req_ue(
LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
}
// Setup the SSB to Rach Occasions mapping according to the config
build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type);
/*
if(mac_cell_group_configP != NULL){
if(mac_cell_group_configP->drx_Config != NULL ){
+6 -1
View File
@@ -63,7 +63,11 @@
#include "NR_PhysicalCellGroupConfig.h"
#include "NR_CellGroupConfig.h"
#include "NR_ServingCellConfig.h"
#include "NR_MeasConfig.h"
#include "fapi_nr_ue_interface.h"
#include "NR_IF_Module.h"
#include "PHY/defs_nr_common.h"
#include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h"
#define NB_NR_UE_MAC_INST 1
/*!\brief Maximum number of logical channl group IDs */
@@ -158,6 +162,7 @@ typedef struct {
NR_CellGroupConfig_t *scg;
NR_RACH_ConfigDedicated_t *rach_ConfigDedicated;
int servCellIndex;
NR_CSI_ReportConfig_t *csirc;
//// MAC config
NR_DRX_Config_t *drx_Config;
NR_SchedulingRequestConfig_t *schedulingRequestConfig;
+5 -2
View File
@@ -267,6 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
@param nr_tti_tx slot for PRACH transmission
@returns indication to generate PRACH to phy */
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id,
int CC_id,
UE_MODE_t UE_mode,
@@ -278,15 +279,14 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
@param module_idP Index of UE instance
@param CC_id Component Carrier Index
@param gNB_index gNB index
@param t_id
@param rach_ConfigDedicated
@returns void */
void nr_get_prach_resources(module_id_t mod_id,
int CC_id,
uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id);
@@ -305,5 +305,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
uint8_t *nb_dmrs_re_per_rb,
uint16_t *number_dmrs_symbols);
void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired);
#endif
/** @}*/
+88 -27
View File
@@ -75,9 +75,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
void nr_get_prach_resources(module_id_t mod_id,
int CC_id,
uint8_t gNB_id,
uint8_t t_id,
uint8_t first_Msg3,
NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){
NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
@@ -87,8 +87,8 @@ void nr_get_prach_resources(module_id_t mod_id,
// NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size;
int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0;
uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size;
AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
@@ -100,6 +100,7 @@ void nr_get_prach_resources(module_id_t mod_id,
//////////* UE Random Access Resource Selection *//////////
///////////////////////////////////////////////////////////
// todo:
// - switch initialisation cases
// -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
@@ -129,12 +130,81 @@ void nr_get_prach_resources(module_id_t mod_id,
// rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
// Determine the SSB to RACH mapping ratio
// =======================================
NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
long cb_preambles_per_ssb; // Nb of preambles per SSB
int total_preambles_per_ssb;
int starting_preamble_nb = 0;
uint8_t ssb_nb_in_ro;
switch (ssb_perRACH_config){
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
multiple_ssb_per_ro = false;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 1;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 2;
cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 4;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 8;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
break;
case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
multiple_ssb_per_ro = true;
ssb_rach_ratio = 16;
cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
break;
default:
AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
break;
}
Msg3_size = mac->RA_Msg3_size;
numberOfRA_Preambles = 64;
if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
// Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration
if ((true == multiple_ssb_per_ro) &&
(ssb_rach_ratio > 1)) {
total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio;
ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro;
starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
}
else {
total_preambles_per_ssb = numberOfRA_Preambles;
starting_preamble_nb = 0;
}
if (!nr_rach_ConfigCommon->groupBconfigured) {
noGroupB = 1;
} else {
@@ -220,29 +290,30 @@ void nr_get_prach_resources(module_id_t mod_id,
if (first_Msg3 == 1) {
if (noGroupB == 1) {
// use Group A preamble
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
mac->RA_usedGroupA = 1;
} else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
// Group B is configured and RA preamble Group A is used
// - todo add condition on CCCH_sdu_size for initiation by CCCH
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
mac->RA_usedGroupA = 1;
} else {
// Group B preamble is configured and used
// the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
// the remaining belong to RA Preambles Group B
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
mac->RA_usedGroupA = 0;
}
} else { // Msg3 is being retransmitted
if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
} else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
} else {
prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
}
}
LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
}
@@ -268,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id,
// 1) this does not apply to contention-free RA Preamble for beam failure recovery request
// 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
// ra_RNTI computation
// - todo: this is for TDD FR1 only
// - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
// - f_id: index of the PRACH occasion in the frequency domain
// - s_id is starting symbol of the PRACH occasion [0...14]
// - t_id is the first slot of the PRACH occasion in a system frame [0...80]
ul_carrier_id = 0; // NUL
f_id = rach_ConfigGeneric->msg1_FrequencyStart;
SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4];
s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5];
f_id = prach_pdu->num_ra;
t_id = prach_pdu->prach_slot;
s_id = prach_pdu->prach_start_symbol;
// Pick the first slot of the PRACH occasion in a system frame
for (i = 0; i < 10; i++){
if (((SFN_nbr & (1 << i)) >> i) == 1){
t_id = 2*i;
break;
}
}
prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
mac->ra_rnti = prach_resources->ra_RNTI;
@@ -335,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
fapi_nr_ul_config_prach_pdu *prach_pdu,
module_id_t mod_id,
int CC_id,
UE_MODE_t UE_mode,
@@ -363,7 +424,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
if (UE_mode < PUSCH && prach_resources->init_msg1) {
if (prach_resources->init_msg1) {
LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
@@ -449,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus, // sdus buffer
(uint8_t *) payload, // UL MAC pdu pointer
@@ -576,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
} else {
@@ -590,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
// Fill in preamble and PRACH resources
if (mac->generate_nr_prach == 1)
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
}
}
File diff suppressed because it is too large Load Diff
+8 -1
View File
@@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
if (ue_mac->RA_RAPID_found) {
uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc;
unsigned char tpc_command, csi_req;
unsigned char tpc_command;
#ifdef DEBUG_RAR
unsigned char csi_req;
#endif
// TC-RNTI
*t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
ue_mac->t_crnti = *t_crnti;
// TA command
ta_command = rar->TA2 + (rar->TA1 << 5);
#ifdef DEBUG_RAR
// CSI
csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
#endif
// TPC
tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
switch (tpc_command){
+3 -1
View File
@@ -128,7 +128,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
uint16_t band;
int32_t offset;
get_band((cfg->carrier_config.dl_frequency.value)*1000,
get_band(((uint64_t)cfg->carrier_config.dl_frequency.value)*1000,
&band,
&offset,
&frame_type);
@@ -315,6 +315,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm
}
int rrc_mac_config_req_gNB(module_id_t Mod_idP,
int ssb_SubcarrierOffset,
int pdsch_AntennaPorts,
@@ -367,6 +368,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
if (add_ue == 1 && get_softmodem_params()->phy_test) {
const int UE_id = add_new_nr_ue(Mod_idP,rnti);
UE_info->secondaryCellGroup[UE_id] = secondaryCellGroup;
compute_csi_bitlen (secondaryCellGroup, UE_info, UE_id);
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList =
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
+83 -60
View File
@@ -344,9 +344,8 @@ void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
sub_frame_t slotP) {
uint16_t O_uci;
uint16_t O_ack;
uint8_t SR_flag = 0; // no SR in PUCCH implemented for now
uint16_t O_csi, O_ack, O_uci;
uint8_t O_sr = 0; // no SR in PUCCH implemented for now
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
@@ -359,31 +358,36 @@ void nr_schedule_pucch(int Mod_idP,
NR_sched_pucch *curr_pucch;
for (int k=0; k<nr_ulmix_slots; k++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k];
if ((curr_pucch->dai_c > 0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
UL_tti_req->SFN = curr_pucch->frame;
UL_tti_req->Slot = curr_pucch->ul_slot;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
UL_tti_req->n_pdus+=1;
for (int l=0; l<2; l++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
O_ack = curr_pucch->dai_c;
O_uci = O_ack; // for now we are just sending acknacks in pucch
O_csi = curr_pucch->csi_bits;
O_uci = O_ack + O_csi + O_sr;
if ((O_uci>0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
UL_tti_req->SFN = curr_pucch->frame;
UL_tti_req->Slot = curr_pucch->ul_slot;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
nfapi_nr_pucch_pdu_t *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
UL_tti_req->n_pdus+=1;
LOG_D(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP);
LOG_I(MAC,"Scheduling pucch reception for frame %d slot %d with (%d, %d, %d) (SR ACK, CSI) bits\n",
frameP,slotP,O_sr,O_ack,curr_pucch->csi_bits);
nr_configure_pucch(pucch_pdu,
scc,
ubwp,
curr_pucch->resource_indicator,
O_uci,
O_ack,
SR_flag);
nr_configure_pucch(pucch_pdu,
scc,
ubwp,
UE_info->rnti[UE_id],
curr_pucch->resource_indicator,
O_csi,
O_ack,
O_sr);
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
0,
sizeof(NR_sched_pucch));
}
}
}
}
@@ -395,9 +399,12 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
frame_t frame,
sub_frame_t slot){
protocol_ctxt_t ctxt;
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP);
int nb_periods_per_frame;
const int UE_id = 0;
const int bwp_id = 1;
@@ -406,24 +413,49 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
NR_COMMON_channels_t *cc = gNB->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
const int num_slots_per_tdd = slots_per_frame[*scc->ssbSubcarrierSpacing] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
if (slot == 0 && UE_info->active[UE_id]) {
for (int k=0; k<nr_ulmix_slots; k++) {
/* Seems to be covered 384? */
/*memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));*/
/* Seems to be covered in line 335? */
/*memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k],
0,
sizeof(NR_sched_pusch));*/
}
switch(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) {
case 0:
nb_periods_per_frame = 20; // 10ms/0p5ms
break;
case 1:
nb_periods_per_frame = 16; // 10ms/0p625ms
break;
case 2:
nb_periods_per_frame = 10; // 10ms/1ms
break;
case 3:
nb_periods_per_frame = 8; // 10ms/1p25ms
break;
case 4:
nb_periods_per_frame = 5; // 10ms/2ms
break;
case 5:
nb_periods_per_frame = 4; // 10ms/2p5ms
break;
case 6:
nb_periods_per_frame = 2; // 10ms/5ms
break;
case 7:
nb_periods_per_frame = 1; // 10ms/10ms
break;
default:
AssertFatal(1==0,"Undefined tdd period %d\n", scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
}
int num_slots_per_tdd = (slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame;
const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
@@ -446,18 +478,18 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
//mbsfn_status[CC_id] = 0;
// clear vrb_maps
memset(cc[CC_id].vrb_map, 0, 275);
memset(cc[CC_id].vrb_map_UL, 0, 275);
memset(cc[CC_id].vrb_map, 0, sizeof(uint16_t) * 275);
memset(cc[CC_id].vrb_map_UL, 0, sizeof(uint16_t) * 275);
clear_nr_nfapi_information(RC.nrmac[module_idP], CC_id, frame, slot);
}
if ((slot == 0) && (frame & 127) == 0) dump_mac_stats(RC.nrmac[module_idP]);
// This schedules MIB
if((slot == 0) && (frame & 7) == 0){
schedule_nr_mib(module_idP, frame, slot);
}
schedule_nr_mib(module_idP, frame, slot, slots_per_frame[*scc->ssbSubcarrierSpacing]);
// This schedule PRACH if we are not in phy_test mode
if (get_softmodem_params()->phy_test == 0)
@@ -466,8 +498,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
// This schedule SR
// TODO
// This schedule CSI
// TODO
// This schedule CSI measurement reporting
if (UE_info->active[UE_id])
nr_csi_meas_reporting(module_idP, UE_id, frame, slot, num_slots_per_tdd, nr_ulmix_slots, slots_per_frame[*scc->ssbSubcarrierSpacing]);
// This schedule RA procedure if not in phy_test mode
// Otherwise already consider 5G already connected
@@ -475,40 +508,30 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
if (get_softmodem_params()->phy_test == 0) {
nr_schedule_RA(module_idP, frame, slot);
nr_schedule_reception_msg3(module_idP, 0, frame, slot);
}
if (UE_info->active[UE_id]) {
// TbD once RACH is available, start ta_timer when UE is connected
if (ue_sched_ctl->ta_timer)
ue_sched_ctl->ta_timer--;
if (ue_sched_ctl->ta_timer == 0) {
ue_sched_ctl->ta_apply = true;
/* if time is up, then set the timer to not send it for 5 frames
// regardless of the TA value */
ue_sched_ctl->ta_timer = 100;
}
}
// This schedules the DCI for Uplink and subsequently PUSCH
// The decision about whether to schedule is done for each UE independently
// inside
if (UE_info->active[UE_id] && slot < 10) {
int tda = 1; // time domain assignment hardcoded for now
schedule_fapi_ul_pdu(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, tda, ulsch_in_slot_bitmap);
nr_schedule_pusch(module_idP, UE_id, num_slots_per_tdd, nr_ulmix_slots, frame, slot);
}
if (UE_info->active[UE_id]
&& (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot % num_slots_per_tdd))
&& slot < 10) {
ue_sched_ctl->current_harq_pid = slot % num_slots_per_tdd;
//int pucch_sched;
//nr_update_pucch_scheduling(module_idP, UE_id, frame, slot, num_slots_per_tdd,&pucch_sched);
//nr_schedule_uss_dlsch_phytest(module_idP, frame, slot, &UE_info->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL);
nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd);
ue_sched_ctl->ta_apply = false;
}
if (UE_info->active[UE_id])
nr_schedule_pucch(module_idP, UE_id, nr_ulmix_slots, frame, slot);
@@ -448,9 +448,11 @@ void nr_initiate_ra_proc(module_id_t module_idP,
break;
}
}
if (!pr_found) {
LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
module_idP, preamble_index);
return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
}
// This should be handled differently when we use the initialBWP for RA
@@ -931,8 +933,12 @@ void nr_generate_Msg2(module_id_t module_idP,
nr_mac->TX_req[CC_id].Slot = slotP;
memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id),
T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */,
T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length));
/* mark the corresponding RBs as used */
uint8_t *vrb_map = cc[CC_id].vrb_map;
uint16_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
vrb_map[rb + pdsch_pdu_rel15->rbStart] = 1;
}
+131 -76
View File
@@ -56,7 +56,7 @@
extern RAN_CONTEXT_t RC;
extern uint8_t SSB_Table[38];
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, uint8_t slots_per_frame){
gNB_MAC_INST *gNB = RC.nrmac[module_idP];
NR_COMMON_channels_t *cc;
@@ -67,93 +67,148 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){
int mib_sdu_length;
int CC_id;
AssertFatal(slotP == 0, "Subframe must be 0\n");
AssertFatal((frameP & 7) == 0, "Frame must be a multiple of 8\n");
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
dl_tti_request = &gNB->DL_req[CC_id];
dl_req = &dl_tti_request->dl_tti_request_body;
cc = &gNB->common_channels[CC_id];
#if 0
//SSB is transmitted based on SSB periodicity
if((frameP % cfg->ssb_table.ssb_period.value) == 0) {
uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
uint32_t ssb_index = -1;
for (int i=0; i<2; i++) { // max two SSB per slot
ssb_index = i + SSB_Table[slotP]; // computing the ssb_index
if ((ssb_index<64) && ((L_ssb >> (63-ssb_index)) & 0x01)) { // generating the ssb only if the bit of L_ssb at current ssb index is 1
#endif
const long band = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
const uint32_t ssb_offset0 = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
int ratio;
switch (*cc->ServingCellConfigCommon->ssbSubcarrierSpacing) {
case NR_SubcarrierSpacing_kHz15:
AssertFatal(band <= 79,
"Band %ld is not possible for SSB with 15 kHz SCS\n",
band);
if (band < 77) // below 3GHz
ratio = 3; // NRARFCN step is 5 kHz
else
ratio = 1; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz30:
AssertFatal(band <= 79,
"Band %ld is not possible for SSB with 15 kHz SCS\n",
band);
if (band < 77) // below 3GHz
ratio = 6; // NRARFCN step is 5 kHz
else
ratio = 2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz120:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 120 kHz SCS\n",
band);
ratio = 2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz240:
AssertFatal(band >= 257,
"Band %ld is not possible for SSB with 240 kHz SCS\n",
band);
ratio = 4; // NRARFCN step is 15 kHz
break;
default:
AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n",
*cc->ServingCellConfigCommon->ssbSubcarrierSpacing);
}
mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]); // not used in this case
// scheduling MIB every 8 frames, PHY repeats it in between
if((slotP == 0) && (frameP & 7) == 0) {
dl_tti_request = &gNB->DL_req[CC_id];
dl_req = &dl_tti_request->dl_tti_request_body;
LOG_D(MAC, "Frame %d, slot %d: BCH PDU length %d\n", frameP, slotP, mib_sdu_length);
mib_sdu_length = mac_rrc_nr_data_req(module_idP, CC_id, frameP, MIBCH, 1, &cc->MIB_pdu.payload[0]);
if (mib_sdu_length > 0) {
LOG_D(MAC, "Frame %d, slot %d: BCH PDU length %d\n", frameP, slotP, mib_sdu_length);
LOG_D(MAC, "Frame %d, slot %d: Adding BCH PDU in position %d (length %d)\n", frameP, slotP, dl_req->nPDUs, mib_sdu_length);
if (mib_sdu_length > 0) {
LOG_D(MAC,
"Frame %d, slot %d: Adding BCH PDU in position %d (length %d)\n",
frameP,
slotP,
dl_req->nPDUs,
mib_sdu_length);
if ((frameP & 1023) < 80){
LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
if ((frameP & 1023) < 80){
LOG_I(MAC,"[gNB %d] Frame %d : MIB->BCH CC_id %d, Received %d bytes\n",module_idP, frameP, CC_id, mib_sdu_length);
}
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE;
dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t);
AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n");
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count);
AssertFatal(cc->ServingCellConfigCommon->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n");
const nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; //kSSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10; // absoluteFrequencySSB is the center of SSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1);
dl_req->nPDUs++;
}
}
dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_config_pdu->PDUType = NFAPI_NR_DL_TTI_SSB_PDU_TYPE;
dl_config_pdu->PDUSize =2 + sizeof(nfapi_nr_dl_tti_ssb_pdu_rel15_t);
AssertFatal(cc->ServingCellConfigCommon->physCellId!=NULL,"cc->ServingCellConfigCommon->physCellId is null\n");
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.PhysCellId = *cc->ServingCellConfigCommon->physCellId;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.BetaPss = 0;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = 0;//ssb_index ;//SSB index for each SSB
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon!=NULL,"scc->downlinkConfigCommonL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB!=NULL,"scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count==1,"Frequency Band list does not have 1 element (%d)\n",cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count);
AssertFatal(cc->ServingCellConfigCommon->ssbSubcarrierSpacing,"ssbSubcarrierSpacing is null\n");
AssertFatal(cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],"band is null\n");
long band = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
uint32_t ssb_offset0 = *cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - cc->ServingCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
int ratio;
switch (*cc->ServingCellConfigCommon->ssbSubcarrierSpacing) {
case NR_SubcarrierSpacing_kHz15:
AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band);
if (band<77) // below 3GHz
ratio=3; // NRARFCN step is 5 kHz
else
ratio=1; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz30:
AssertFatal(band <= 79, "Band %ld is not possible for SSB with 15 kHz SCS\n",band);
if (band<77) // below 3GHz
ratio=6; // NRARFCN step is 5 kHz
else
ratio=2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz120:
AssertFatal(band >= 257, "Band %ld is not possible for SSB with 120 kHz SCS\n",band);
ratio=2; // NRARFCN step is 15 kHz
break;
case NR_SubcarrierSpacing_kHz240:
AssertFatal(band >= 257, "Band %ld is not possible for SSB with 240 kHz SCS\n",band);
ratio=4; // NRARFCN step is 15 kHz
break;
default:
AssertFatal(1==0,"SCS %ld not allowed for SSB \n", *cc->ServingCellConfigCommon->ssbSubcarrierSpacing);
}
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; //kSSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = ssb_offset0/(ratio*12) - 10;/*cfg->ssb_table.ssb_offset_point_a.value;*/ // absoluteFrequencySSB is the center of SSB
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayloadFlag = 1;
dl_config_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload = (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1);
dl_req->nPDUs++;
uint8_t *vrb_map = cc[CC_id].vrb_map;
const int rbStart = dl_config_pdu->ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA;
for (int rb = 0; rb < 20; rb++)
vrb_map[rbStart + rb] = 1;
// checking if there is any SSB in slot
const int abs_slot = (slots_per_frame * frameP) + slotP;
const int slot_per_period = (slots_per_frame>>1)<<(*cc->ServingCellConfigCommon->ssb_periodicityServingCell);
int eff_120_slot;
const BIT_STRING_t *mediumBitmap = &cc->ServingCellConfigCommon->ssb_PositionsInBurst->choice.mediumBitmap;
uint8_t buf = 0;
switch (cc->ServingCellConfigCommon->ssb_PositionsInBurst->present) {
case 1:
// presence of ssbs possible in the first 2 slots of ssb period
if ((abs_slot % slot_per_period) < 2 &&
(((mediumBitmap->buf[0]) >> (6 - (slotP << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, (ssb_offset0 / (ratio * 12) - 10), CC_id);
break;
case 2:
// presence of ssbs possible in the first 4 slots of ssb period
if ((abs_slot % slot_per_period) < 4 &&
(((mediumBitmap->buf[0]) >> (6 - (slotP << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, (ssb_offset0 / (ratio * 12) - 10), CC_id);
break;
case 3:
AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing ==
NR_SubcarrierSpacing_kHz120,
"240kHZ subcarrier spacing currently not supported for SSBs\n");
if ((abs_slot % slot_per_period) < 8) {
eff_120_slot = slotP;
buf = mediumBitmap->buf[0];
} else if ((abs_slot % slot_per_period) < 17) {
eff_120_slot = slotP - 9;
buf = mediumBitmap->buf[1];
} else if ((abs_slot % slot_per_period) < 26) {
eff_120_slot = slotP - 18;
buf = mediumBitmap->buf[2];
} else if ((abs_slot % slot_per_period) < 35) {
eff_120_slot = slotP - 27;
buf = mediumBitmap->buf[3];
}
if (((buf >> (6 - (eff_120_slot << 1))) & 3) != 0)
fill_ssb_vrb_map(cc, ssb_offset0 / (ratio * 12) - 10, CC_id);
break;
default:
AssertFatal(0,
"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
cc->ServingCellConfigCommon->ssb_PositionsInBurst->present);
}
}
}
void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) {
//----------------------------------------
}
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int CC_id) {
uint16_t *vrb_map = cc[CC_id].vrb_map;
for (int rb = 0; rb < 20; rb++)
vrb_map[rbStart + rb] = 1;
}
+129 -84
View File
@@ -343,68 +343,98 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
return offset;
}
void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) {
void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
// TODO
int max_harq_rounds = 4; // TODO define macro
int num_ucis = UL_info->uci_ind.num_ucis;
nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
for (int i = 0; i < num_ucis; i++) {
switch (uci_list[i].pdu_type) {
case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break;
if (uci_01 != NULL) {
// handle harq
int harq_idx_s = 0;
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
//if (get_softmodem_params()->phy_test == 0) {
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
// handle harq
int harq_idx_s = 0;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) {
// search for the right harq process
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
// if the gNB received ack with a good confidence
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) &&
(uci_pdu->harq->harq_confidence_level == 0)) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
// search for the right harq process
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
// if the gNB received ack with a good confidence
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
(uci_01->harq->harq_confidence_level == 0)) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
//}
break;
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break;
}
}
UL_info->uci_ind.num_ucis = 0;
if (uci_234 != NULL) {
int harq_idx_s = 0;
int acknack;
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
// if the gNB received ack with a good confidence or if the max harq rounds was reached
if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
// TODO add some confidence level for when there is no CRC
if ((uci_234->harq.harq_crc != 1) && acknack) {
// toggle NDI and reset round
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
else
sched_ctrl->harq_processes[harq_idx].round++;
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
harq_idx_s = harq_idx + 1;
// if the max harq rounds was reached
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
stats->dlsch_errors++;
}
break;
}
// if feedback slot processing is aborted
else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
(sched_ctrl->harq_processes[harq_idx].is_waiting)) {
sched_ctrl->harq_processes[harq_idx].round++;
if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
sched_ctrl->harq_processes[harq_idx].round = 0;
}
sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
}
}
}
}
}
int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) {
@@ -453,7 +483,6 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
const int CC_id = 0;
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
sched_ctrl->rbSize = 0;
/* Retrieve amount of data to send for this UE */
sched_ctrl->num_total_bytes = 0;
@@ -470,7 +499,8 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
0,
0);
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
if (sched_ctrl->num_total_bytes == 0 && !get_softmodem_params()->phy_test)
if (sched_ctrl->num_total_bytes == 0
&& !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
return;
LOG_D(MAC,
"%d.%d, DTCH%d->DLSCH, RLC status %d bytes\n",
@@ -505,11 +535,17 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
UE_info->num_pdcch_cand[UE_id][cid]++;
/* Find PUCCH occasion */
nr_update_pucch_scheduling(
module_id, UE_id, frame, slot, num_slots_per_tdd, &sched_ctrl->pucch_sched_idx);
nr_acknack_scheduling(module_id,
UE_id,
frame,
slot,
num_slots_per_tdd,
&sched_ctrl->pucch_sched_idx,
&sched_ctrl->pucch_occ_idx);
AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
uint8_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
const int current_harq_pid = sched_ctrl->current_harq_pid;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
@@ -589,18 +625,26 @@ void nr_schedule_ue_spec(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd) {
/* PREPROCESSOR */
nr_simple_dlsch_preprocessor(module_id, frame, slot, num_slots_per_tdd);
gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
/* PREPROCESSOR */
gNB_mac->pre_processor_dl(module_id, frame, slot, num_slots_per_tdd);
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
const int CC_id = 0;
NR_UE_list_t *UE_list = &UE_info->list;
for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
if (sched_ctrl->rbSize <= 0 && !get_softmodem_params()->phy_test)
/* update TA and set ta_apply every 10 frames.
* Possible improvement: take the periodicity from input file.
* If such UE is not scheduled now, it will be by the preprocessor later.
* If we add the CE, ta_apply will be reset */
if (frame >= (sched_ctrl->ta_frame + 10) % 1023)
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
if (sched_ctrl->rbSize <= 0)
continue;
const rnti_t rnti = UE_info->rnti[UE_id];
@@ -634,34 +678,24 @@ void nr_schedule_ue_spec(module_id_t module_id,
const int current_harq_pid = sched_ctrl->current_harq_pid;
NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid];
NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx];
NR_sched_pucch *pucch = &sched_ctrl->sched_pucch[sched_ctrl->pucch_sched_idx][sched_ctrl->pucch_occ_idx];
harq->feedback_slot = pucch->ul_slot;
harq->is_waiting = 1;
UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
nr_fill_nfapi_dl_pdu(module_id,
UE_id,
sched_ctrl->active_bwp->bwp_Id,
sched_ctrl->search_space,
sched_ctrl->coreset,
dl_req,
rnti,
UE_info->secondaryCellGroup[UE_id],
sched_ctrl,
pucch,
1 /* nrOfLayers */,
sched_ctrl->mcs,
sched_ctrl->rbSize,
sched_ctrl->rbStart,
sched_ctrl->numDmrsCdmGrpsNoData,
getDmrsConfigType(sched_ctrl->active_bwp),
sched_ctrl->mcsTableIdx,
nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
TBS,
sched_ctrl->time_domain_allocation,
startSymbolIndex,
nrOfSymbols,
sched_ctrl->aggregation_level,
sched_ctrl->cce_index,
current_harq_pid,
harq->ndi,
harq->round);
@@ -698,7 +732,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
* nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */
const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0;
/* Get RLC data TODO: remove random data retrieval */
/* Get RLC data */
int header_length_total = 0;
int header_length_last = 0;
int sdu_length_total = 0;
@@ -740,10 +774,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
sdu_length_total += sdu_lengths[num_sdus];
header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
header_length_total += header_length_last;
num_sdus++;
//ue_sched_ctl->uplane_inactivity_timer = 0;
}
else if (get_softmodem_params()->phy_test) {
LOG_D(MAC, "Configuring DL_TX in %d.%d: random data\n", frame, slot);
@@ -760,10 +791,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
// Check if there is data from RLC or CE
const int post_padding = TBS >= 2 + header_length_total + sdu_length_total + ta_len;
// padding param currently not in use
//padding = TBS - header_length_total - sdu_length_total - ta_len - 1;
const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
@@ -804,6 +832,20 @@ void nr_schedule_ue_spec(module_id_t module_id,
retInfo->mcs = sched_ctrl->mcs;
retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
// ta command is sent, values are reset
if (sched_ctrl->ta_apply) {
sched_ctrl->ta_apply = false;
sched_ctrl->ta_frame = frame;
LOG_D(MAC,
"%d.%2d UE %d TA scheduled, resetting TA frame\n",
frame,
slot,
UE_id);
}
T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS));
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frame%100 == 0) {
LOG_I(MAC,
@@ -816,5 +858,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
}
#endif
}
/* mark UE as scheduled */
sched_ctrl->rbSize = 0;
}
}
@@ -252,240 +252,104 @@ void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
}
}
int configure_fapi_dl_pdu_phytest(int Mod_idP,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart) {
gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
/* schedules whole bandwidth for first user, all the time */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd)
{
if (slot != 1)
return; /* only schedule in slot 1 for now */
NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
const int UE_id = 0;
const int CC_id = 0;
AssertFatal(UE_info->active[UE_id],
"%s(): expected UE %d to be active\n",
__func__,
UE_id);
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu;
int TBS;
int bwp_id=1;
int UE_id = 0;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1];
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n");
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0,
"searchPsacesToAddModList is empty\n");
dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));
dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
memset((void*)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));
nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
pdsch_pdu_rel15->pduBitmap = 0;
pdsch_pdu_rel15->rnti = UE_info->rnti[UE_id];
pdsch_pdu_rel15->pduIndex = 0;
// BWP
pdsch_pdu_rel15->BWPSize = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
if (bwp->bwp_Common->genericParameters.cyclicPrefix) pdsch_pdu_rel15->CyclicPrefix = *bwp->bwp_Common->genericParameters.cyclicPrefix;
else pdsch_pdu_rel15->CyclicPrefix=0;
pdsch_pdu_rel15->NrOfCodewords = 1;
int mcs = (mcsIndex!=NULL) ? *mcsIndex : 9;
int current_harq_pid = UE_info->UE_sched_ctrl[UE_id].current_harq_pid;
pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs,0);
pdsch_pdu_rel15->qamModOrder[0] = 2;
pdsch_pdu_rel15->mcsIndex[0] = mcs;
pdsch_pdu_rel15->mcsTable[0] = 0;
pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round];
pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
pdsch_pdu_rel15->nrOfLayers = 1;
pdsch_pdu_rel15->transmissionScheme = 0;
pdsch_pdu_rel15->refPoint = 0; // Point A
UE_info->mac_stats[UE_id].dlsch_rounds[UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round]++;
pdsch_pdu_rel15->dmrsConfigType = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
pdsch_pdu_rel15->SCID = 0;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 1;
pdsch_pdu_rel15->dmrsPorts = 1;
pdsch_pdu_rel15->resourceAlloc = 1;
pdsch_pdu_rel15->rbStart = (rbStart!=NULL) ? *rbStart : 0;
pdsch_pdu_rel15->rbSize = (rbSize!=NULL) ? *rbSize : pdsch_pdu_rel15->BWPSize;
pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
int startSymbolAndLength=0;
int time_domain_assignment=2;
int StartSymbolIndex,NrOfSymbols;
AssertFatal(time_domain_assignment<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count,"time_domain_assignment %d>=%d\n",time_domain_assignment,bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count);
startSymbolAndLength = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength;
SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols);
pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
// k0 = *bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0;
pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
scc->dmrs_TypeA_Position,
pdsch_pdu_rel15->NrOfSymbols);
dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t));
// bwp indicator
int n_dl_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count;
if (n_dl_bwp < 4)
dci_pdu_rel15[0].bwp_indicator.val = bwp_id;
else
dci_pdu_rel15[0].bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212
// frequency domain assignment
if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation==NR_PDSCH_Config__resourceAllocation_resourceAllocationType1)
dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
pdsch_pdu_rel15->rbStart,
NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275));
else
AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");
// time domain assignment
dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV;
// mcs and rv
dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
// harq pid and ndi
dci_pdu_rel15[0].harq_pid = current_harq_pid;
dci_pdu_rel15[0].ndi = UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi;
// DAI
dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3;
// TPC for PUCCH
dci_pdu_rel15[0].tpc = UE_info->UE_sched_ctrl[UE_id].tpc1; // table 7.2.1-1 in 38.213
// PUCCH resource indicator
dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
// PDSCH to HARQ TI
dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator;
UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].feedback_slot = pucch_sched->ul_slot;
UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1;
// antenna ports
dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0
// dmrs sequence initialization
dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID;
LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n",
dci_pdu_rel15[0].frequency_domain_assignment.val,
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275),
dci_pdu_rel15[0].time_domain_assignment.val,
dci_pdu_rel15[0].vrb_to_prb_mapping.val,
dci_pdu_rel15[0].mcs,
dci_pdu_rel15[0].tb_scaling,
dci_pdu_rel15[0].ndi,
dci_pdu_rel15[0].rv);
NR_SearchSpace_t *ss;
int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList!=NULL,"searchPsacesToAddModList is null\n");
AssertFatal(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count>0,
"searchPsacesToAddModList is empty\n");
int found=0;
for (int i=0;i<bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;i++) {
ss=bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.array[i];
AssertFatal(ss->controlResourceSetId != NULL,"ss->controlResourceSetId is null\n");
AssertFatal(ss->searchSpaceType != NULL,"ss->searchSpaceType is null\n");
if (ss->searchSpaceType->present == target_ss) {
found=1;
break;
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
/* find largest unallocated chunk */
const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
int rbStart = 0;
int tStart = 0;
int rbSize = 0;
uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
/* find largest unallocated RB region */
do {
/* advance to first free RB */
while (tStart < bwpSize && vrb_map[tStart])
tStart++;
/* find maximum rbSize at current rbStart */
int tSize = 1;
while (tStart + tSize < bwpSize && !vrb_map[tStart + tSize])
tSize++;
if (tSize > rbSize) {
rbStart = tStart;
rbSize = tSize;
}
}
AssertFatal(found==1,"Couldn't find an adequate searchspace\n");
tStart += tSize;
} while (tStart < bwpSize);
uint8_t nr_of_candidates, aggregation_level;
find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 1 /* dedicated */);
const int cid = coreset->controlResourceSetId;
const uint16_t Y = UE_info->Y[UE_id][cid][nr_mac->current_slot];
sched_ctrl->num_total_bytes = 0;
const int lcid = DL_SCH_LCID_DTCH;
const uint16_t rnti = UE_info->rnti[UE_id];
/* update sched_ctrl->num_total_bytes so that postprocessor schedules data,
* if available */
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
rnti,
module_id,
frame,
slot,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
uint8_t nr_of_candidates;
find_aggregation_candidates(&sched_ctrl->aggregation_level,
&nr_of_candidates,
sched_ctrl->search_space);
sched_ctrl->coreset = get_coreset(
sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
const int cid = sched_ctrl->coreset->controlResourceSetId;
const uint16_t Y = UE_info->Y[UE_id][cid][RC.nrmac[module_id]->current_slot];
const int m = UE_info->num_pdcch_cand[UE_id][cid];
int CCEIndex = allocate_nr_CCEs(nr_mac,
bwp,
coreset,
aggregation_level,
sched_ctrl->cce_index = allocate_nr_CCEs(RC.nrmac[module_id],
sched_ctrl->active_bwp,
sched_ctrl->coreset,
sched_ctrl->aggregation_level,
Y,
m,
nr_of_candidates);
if (CCEIndex < 0) {
LOG_E(MAC, "%s(): CCE list not empty, couldn't schedule PDSCH\n", __func__);
free(dci_pdu_rel15);
return 0;
}
UE_info->num_pdcch_cand[UE_id][cid]++;
AssertFatal(sched_ctrl->cce_index >= 0,
"%s(): could not find CCE for UE %d\n",
__func__,
UE_id);
nr_configure_pdcch(nr_mac,
pdcch_pdu_rel15,
UE_info->rnti[UE_id],
ss,
coreset,
scc,
bwp,
aggregation_level,
CCEIndex);
nr_acknack_scheduling(module_id,
UE_id,
frame,
slot,
num_slots_per_tdd,
&sched_ctrl->pucch_sched_idx,
&sched_ctrl->pucch_occ_idx);
AssertFatal(sched_ctrl->pucch_sched_idx >= 0, "no uplink slot for PUCCH found!\n");
int dci_formats[2];
int rnti_types[2];
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats)
dci_formats[0] = NR_DL_DCI_FORMAT_1_1;
else
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
sched_ctrl->rbStart = rbStart;
sched_ctrl->rbSize = rbSize;
sched_ctrl->time_domain_allocation = 2;
sched_ctrl->mcsTableIdx = 0;
sched_ctrl->mcs = 9;
sched_ctrl->numDmrsCdmGrpsNoData = 1;
rnti_types[0] = NR_RNTI_C;
fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id);
LOG_D(MAC, "DCI params: rnti %x, rnti_type %d, dci_format %d\n \
coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n",
pdcch_pdu_rel15->dci_pdu.RNTI[0],
rnti_types[0],
dci_formats[0],
(unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
pdcch_pdu_rel15->StartSymbolIndex,
pdcch_pdu_rel15->DurationSymbols);
int x_Overhead = 0; // should be 0 for initialBWP
nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu,x_Overhead,pdsch_pdu_rel15->numDmrsCdmGrpsNoData,0);
// Hardcode it for now
TBS = dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15.TBSize[0];
if (UE_info->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round==0)
UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d startSymbolAndLength %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS: %d\n",
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
startSymbolAndLength,
pdsch_pdu_rel15->StartSymbolIndex,
pdsch_pdu_rel15->NrOfSymbols,
pdsch_pdu_rel15->nrOfLayers,
pdsch_pdu_rel15->NrOfCodewords,
pdsch_pdu_rel15->mcsIndex[0],
TBS);
free(dci_pdu_rel15);
return TBS; //Return TBS in bytes
/* mark the corresponding RBs as used */
for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
vrb_map[rb + sched_ctrl->rbStart] = 1;
}
void config_uldci(NR_BWP_Uplink_t *ubwp,
@@ -564,231 +428,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
}
void configure_fapi_dl_Tx(module_id_t Mod_idP,
frame_t frameP,
sub_frame_t slotP,
nfapi_nr_dl_tti_request_body_t *dl_req,
nfapi_nr_pdu_t *tx_req,
int tbs_bytes,
int16_t pdu_index){
int CC_id = 0;
nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
gNB_MAC_INST *nr_mac = RC.nrmac[Mod_idP];
LOG_D(MAC, "DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d nb_layers %d nb_codewords %d mcs %d TBS (bytes): %d\n",
pdsch_pdu_rel15->rbStart,
pdsch_pdu_rel15->rbSize,
pdsch_pdu_rel15->StartSymbolIndex,
pdsch_pdu_rel15->NrOfSymbols,
pdsch_pdu_rel15->nrOfLayers,
pdsch_pdu_rel15->NrOfCodewords,
pdsch_pdu_rel15->mcsIndex[0],
tbs_bytes);
dl_req->nPDUs+=2;
tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
tx_req->PDU_index = nr_mac->pdu_index[0]++;
tx_req->num_TLV = 1;
tx_req->TLVs[0].length = tbs_bytes +2;
memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&nr_mac->UE_info.DLSCH_pdu[0][0].payload[0], tbs_bytes);
nr_mac->TX_req[CC_id].Number_of_PDUs++;
nr_mac->TX_req[CC_id].SFN = frameP;
nr_mac->TX_req[CC_id].Slot = slotP;
}
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *dlsch_config){
LOG_D(MAC, "In nr_schedule_uss_dlsch_phytest frame %d slot %d\n",frameP,slotP);
int post_padding = 0, header_length_total = 0, sdu_length_total = 0, num_sdus = 0;
int lcid, offset, i, header_length_last, TBS_bytes = 0;
int UE_id = 0, CC_id = 0;
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
//NR_COMMON_channels_t *cc = nr_mac->common_channels;
//NR_ServingCellConfigCommon_t *scc=cc->ServingCellConfigCommon;
nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[gNB_mac->TX_req[CC_id].Number_of_PDUs];
mac_rlc_status_resp_t rlc_status;
NR_UE_info_t *UE_info = &gNB_mac->UE_info;
if (UE_info->num_UEs ==0) return;
unsigned char sdu_lcids[NB_RB_MAX] = {0};
uint16_t sdu_lengths[NB_RB_MAX] = {0};
uint16_t rnti = UE_info->rnti[UE_id];
NR_UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
uint8_t mac_sdus[MAX_NR_DLSCH_PAYLOAD_BYTES];
LOG_D(MAC, "Scheduling UE specific search space DCI type 1\n");
int ta_len = (ue_sched_ctl->ta_apply)?2:0;
TBS_bytes = configure_fapi_dl_pdu_phytest(
module_idP,
dl_req,
pucch_sched,
dlsch_config != NULL ? dlsch_config->mcsIndex : NULL,
dlsch_config != NULL ? &dlsch_config->rbSize : NULL,
dlsch_config != NULL ? &dlsch_config->rbStart : NULL);
if (TBS_bytes == 0)
return;
lcid = DL_SCH_LCID_DTCH;
//for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) {
// TODO: check if the lcid is active
LOG_D(MAC, "[gNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (TBS %d bytes, len %d)\n",
module_idP, frameP, lcid, TBS_bytes, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3);
//if (TBS_bytes - ta_len - header_length_total - sdu_length_total - 3 > 0) {
rlc_status = mac_rlc_status_ind(module_idP,
rnti,
module_idP,
frameP,
slotP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
0,
0);
if (rlc_status.bytes_in_buffer > 0) {
LOG_I(MAC, "configure fapi due to data availability \n");
LOG_I(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d), TBS_bytes: %d \n \n",
module_idP, frameP, TBS_bytes - ta_len - header_length_total - sdu_length_total - 3,
lcid, header_length_total, TBS_bytes);
sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,
rnti,
module_idP,
frameP,
ENB_FLAG_YES,
MBMS_FLAG_NO,
lcid,
TBS_bytes - ta_len - header_length_total - sdu_length_total - 3,
(char *)&mac_sdus[sdu_length_total],
0,
0);
LOG_W(MAC, "[gNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", module_idP, sdu_lengths[num_sdus], lcid);
sdu_lcids[num_sdus] = lcid;
sdu_length_total += sdu_lengths[num_sdus];
header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128);
header_length_total += header_length_last;
num_sdus++;
//ue_sched_ctl->uplane_inactivity_timer = 0;
}
else {
LOG_D(MAC,"Configuring DL_TX in %d.%d\n", frameP, slotP);
// fill dlsch_buffer with random data
for (i = 0; i < TBS_bytes; i++){
mac_sdus[i] = (unsigned char) (lrand48()&0xff);
//((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0])[i] = (unsigned char) (lrand48()&0xff);
}
//Sending SDUs with size 1
//Initialize elements of sdu_lcids and sdu_lengths
sdu_lcids[0] = 0x3f; // DRB
sdu_lengths[0] = TBS_bytes - ta_len - 3;
header_length_total += 2 + (sdu_lengths[0] >= 128);
sdu_length_total += sdu_lengths[0];
num_sdus +=1;
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frameP%100 == 0){
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) {
LOG_I(MAC, "%x. ", ((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[CC_id][0][0].payload[0])[i]);
}
}
#endif
}
UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
// there is at least one SDU or TA command
// if (num_sdus > 0 ){
if (ta_len + sdu_length_total + header_length_total > 0) {
// Check if there is data from RLC or CE
if (TBS_bytes >= 2 + header_length_total + sdu_length_total + ta_len) {
// we have to consider padding
// padding param currently not in use
//padding = TBS_bytes - header_length_total - sdu_length_total - ta_len - 1;
post_padding = 1;
} else {
//padding = 0;
post_padding = 0;
}
offset = nr_generate_dlsch_pdu(module_idP,
&UE_info->UE_sched_ctrl[UE_id],
(unsigned char *) mac_sdus,
(unsigned char *) gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0],
num_sdus, //num_sdus
sdu_lengths,
sdu_lcids,
255, // no drx
NULL, // contention res id
post_padding);
// Padding: fill remainder of DLSCH with 0
if (post_padding > 0){
for (int j = 0; j < (TBS_bytes - offset); j++)
gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0][offset + j] = 0; // mac_pdu[offset + j] = 0;
}
configure_fapi_dl_Tx(module_idP, frameP, slotP, dl_req, tx_req, TBS_bytes, gNB_mac->pdu_index[CC_id]);
if(IS_SOFTMODEM_NOS1){
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) { // TBS_bytes dlsch_pdu_rel15->transport_block_size/8 6784/8
LOG_I(MAC, "%x. ", mac_payload[i]);
}
#endif
} else {
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
if (frameP%100 == 0){
LOG_I(MAC, "Printing first 10 payload bytes at the gNB side, Frame: %d, slot: %d, TBS size: %d \n", frameP, slotP, TBS_bytes);
for(int i = 0; i < 10; i++) {
LOG_I(MAC, "byte %d : %x\n", i,((uint8_t *)gNB_mac->UE_info.DLSCH_pdu[0][0].payload[0])[i]); //LOG_I(MAC, "%x. ", mac_payload[i]);
}
}
#endif
}
}
else { // There is no data from RLC or MAC header, so don't schedule
}
}
int8_t select_ul_harq_pid(NR_UE_sched_ctrl_t *sched_ctrl) {
uint8_t hrq_id;
@@ -980,7 +619,7 @@ void schedule_fapi_ul_pdu(int Mod_idP,
pusch_pdu->resource_alloc = 1; //type 1
pusch_pdu->rb_start = 0;
if (get_softmodem_params()->phy_test==1)
pusch_pdu->rb_size = 50;
pusch_pdu->rb_size = min(pusch_pdu->bwp_size,50);
else
pusch_pdu->rb_size = pusch_pdu->bwp_size;
}
@@ -432,27 +432,17 @@ void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
}
void nr_fill_nfapi_dl_pdu(int Mod_idP,
int UE_id,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
nfapi_nr_dl_tti_request_body_t *dl_req,
rnti_t rnti,
NR_CellGroupConfig_t *secondaryCellGroup,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_sched_pucch *pucch_sched,
int nrOfLayers,
uint8_t mcs,
uint16_t rbSize,
uint16_t rbStart,
uint8_t numDmrsCdmGrpsNoData,
nfapi_nr_dmrs_type_e dmrsConfigType,
uint8_t table_idx,
uint16_t R,
uint8_t Qm,
uint32_t TBS,
int time_domain_assignment,
int StartSymbolIndex,
int NrOfSymbols,
uint8_t aggregation_level,
int CCEIndex,
int harq_pid,
int ndi,
int round) {
@@ -460,9 +450,10 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
NR_COMMON_channels_t *cc = nr_mac->common_channels;
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
const int bwp_id = sched_ctrl->active_bwp->bwp_Id;
const int nrOfLayers = 1;
const int mcs = sched_ctrl->mcs;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
@@ -487,7 +478,7 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdsch_pdu_rel15->pduBitmap = 0;
pdsch_pdu_rel15->rnti = UE_info->rnti[UE_id];
pdsch_pdu_rel15->rnti = rnti;
pdsch_pdu_rel15->pduIndex = nr_mac->pdu_index[0]++;
// BWP
@@ -512,20 +503,19 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdsch_pdu_rel15->dmrsConfigType = dmrsConfigType;
pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
pdsch_pdu_rel15->SCID = 0;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = numDmrsCdmGrpsNoData;
pdsch_pdu_rel15->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
pdsch_pdu_rel15->dmrsPorts = 1;
pdsch_pdu_rel15->resourceAlloc = 1;
pdsch_pdu_rel15->rbStart = rbStart;
pdsch_pdu_rel15->rbSize = rbSize;
pdsch_pdu_rel15->rbStart = sched_ctrl->rbStart;
pdsch_pdu_rel15->rbSize = sched_ctrl->rbSize;
pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
pdsch_pdu_rel15->targetCodeRate[0] = R;
pdsch_pdu_rel15->qamModOrder[0] = Qm;
pdsch_pdu_rel15->TBSize[0] = TBS;
pdsch_pdu_rel15->mcsTable[0] = table_idx;
pdsch_pdu_rel15->mcsTable[0] = sched_ctrl->mcsTableIdx;
pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
// k0 = *bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0;
pdsch_pdu_rel15->dlDmrsSymbPos =
fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
scc->dmrs_TypeA_Position,
@@ -550,8 +540,8 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
275));
else
AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");
// time domain assignment
dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV;
// time domain assignment: row index used instead of SLIV
dci_pdu_rel15[0].time_domain_assignment.val = sched_ctrl->time_domain_allocation;
// mcs and rv
dci_pdu_rel15[0].mcs = mcs;
dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0];
@@ -562,7 +552,7 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3;
// TPC for PUCCH
dci_pdu_rel15[0].tpc = UE_info->UE_sched_ctrl[UE_id].tpc1; // table 7.2.1-1 in 38.213
dci_pdu_rel15[0].tpc = sched_ctrl->tpc1; // table 7.2.1-1 in 38.213
// PUCCH resource indicator
dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator;
// PDSCH to HARQ TI
@@ -587,18 +577,18 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
nr_configure_pdcch(nr_mac,
pdcch_pdu_rel15,
UE_info->rnti[UE_id],
ss,
coreset,
rnti,
sched_ctrl->search_space,
sched_ctrl->coreset,
scc,
bwp,
aggregation_level,
CCEIndex);
sched_ctrl->aggregation_level,
sched_ctrl->cce_index);
int dci_formats[2];
int rnti_types[2];
if (ss->searchSpaceType->choice.ue_Specific->dci_Formats)
if (sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats)
dci_formats[0] = NR_DL_DCI_FORMAT_1_1;
else
dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
@@ -618,17 +608,6 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
pdcch_pdu_rel15->StartSymbolIndex,
pdcch_pdu_rel15->DurationSymbols);
// I don't know why the following is not needed, but in this case we don't
// need additional calculations:
//const uint16_t N_RE_prime = NR_NB_SC_PER_RB * N_sh_symb - N_PRB_DMRS - N_PRB_oh;
//LOG_D(MAC,
// "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n",
// N_RE_prime,
// N_sh_symb,
// N_PRB_DMRS,
// N_PRB_oh);
//pdsch_pdu_rel15->nb_mod_symbols = N_RE_prime*pdsch_pdu_rel15->n_prb*pdsch_pdu_rel15->nb_codewords;
LOG_D(MAC,
"DLSCH PDU: start PRB %d n_PRB %d start symbol %d nb_symbols %d "
"nb_layers %d nb_codewords %d mcs %d TBS: %d\n",
@@ -735,10 +714,11 @@ void nr_configure_pdcch(gNB_MAC_INST *nr_mac,
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint16_t rnti,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_csi,
uint16_t O_ack,
uint8_t SR_flag) {
uint8_t O_sr) {
NR_PUCCH_Config_t *pucch_Config;
NR_PUCCH_Resource_t *pucchres;
@@ -753,6 +733,8 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->bit_len_harq = O_ack;
uint16_t O_uci = O_csi + O_ack;
if (bwp) { // This is not the InitialBWP
NR_PUSCH_Config_t *pusch_Config = bwp->bwp_Dedicated->pusch_Config->choice.setup;
@@ -815,7 +797,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
else
AssertFatal(1==0,"Couldn't fine pucch resource indicator %d in PUCCH resource set %d for %d UCI bits",pucch_resource,i,O_uci);
}
else {
if (pucchresset->pucch_ResourceSetId == 1 && O_uci>2) {
N3 = pucchresset->maxPayloadMinus1!= NULL ? *pucchresset->maxPayloadMinus1 : 1706;
if (N2<O_uci && N3>O_uci) {
if (pucch_resource < n_list)
@@ -841,6 +823,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
if (pucchres->pucch_ResourceId == *resource_id) {
res_found = 1;
pucch_pdu->prb_start = pucchres->startingPRB;
pucch_pdu->rnti = rnti;
// FIXME why there is only one frequency hopping flag
// what about inter slot frequency hopping?
pucch_pdu->freq_hop_flag = pucchres->intraSlotFrequencyHopping!= NULL ? 1 : 0;
@@ -851,7 +834,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->initial_cyclic_shift = pucchres->format.choice.format0->initialCyclicShift;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
pucch_pdu->sr_flag = SR_flag;
pucch_pdu->sr_flag = O_sr;
break;
case NR_PUCCH_Resource__format_PR_format1 :
pucch_pdu->format_type = 1;
@@ -859,21 +842,23 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
pucch_pdu->time_domain_occ_idx = pucchres->format.choice.format1->timeDomainOCC;
pucch_pdu->sr_flag = SR_flag;
pucch_pdu->sr_flag = O_sr;
break;
case NR_PUCCH_Resource__format_PR_format2 :
pucch_pdu->format_type = 2;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format2->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
pucch_pdu->dmrs_scrambling_id = id0!= NULL ? *id0 : *scc->physCellId;
pucch_pdu->prb_size = compute_pucch_prb_size(2,pucchres->format.choice.format2->nrofPRBs,
O_uci+O_sr,O_csi,pucch_Config->format2->choice.setup->maxCodeRate,
2,pucchres->format.choice.format2->nrofSymbols,8);
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
case NR_PUCCH_Resource__format_PR_format3 :
pucch_pdu->format_type = 3;
pucch_pdu->nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
pucch_pdu->start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
pucch_pdu->prb_size = pucchres->format.choice.format3->nrofPRBs;
pucch_pdu->data_scrambling_id = pusch_id!= NULL ? *pusch_id : *scc->physCellId;
if (pucch_Config->format3 == NULL) {
pucch_pdu->pi_2bpsk = 0;
@@ -884,6 +869,19 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
int f3_dmrs_symbols;
if (pucchres->format.choice.format3->nrofSymbols==4)
f3_dmrs_symbols = 1<<pucch_pdu->freq_hop_flag;
else {
if(pucchres->format.choice.format3->nrofSymbols<10)
f3_dmrs_symbols = 2;
else
f3_dmrs_symbols = 2<<pucch_pdu->add_dmrs_flag;
}
pucch_pdu->prb_size = compute_pucch_prb_size(3,pucchres->format.choice.format3->nrofPRBs,
O_uci+O_sr,O_csi,pucch_Config->format3->choice.setup->maxCodeRate,
2-pucch_pdu->pi_2bpsk,pucchres->format.choice.format3->nrofSymbols-f3_dmrs_symbols,12);
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
case NR_PUCCH_Resource__format_PR_format4 :
pucch_pdu->format_type = 4;
@@ -901,6 +899,7 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
pucch_pdu->pi_2bpsk = pucchfmt->pi2BPSK!= NULL ? 1 : 0;
pucch_pdu->add_dmrs_flag = pucchfmt->additionalDMRS!= NULL ? 1 : 0;
}
pucch_pdu->bit_len_csi_part1 = O_csi;
break;
default :
AssertFatal(1==0,"Undefined PUCCH format \n");
@@ -916,6 +915,84 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
}
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_tot,
uint16_t O_csi,
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
uint8_t Qm,
uint8_t n_symb,
uint8_t n_re_ctrl) {
uint16_t O_crc;
if (O_tot<12)
O_crc = 0;
else{
if (O_tot<20)
O_crc = 6;
else {
if (O_tot<360)
O_crc = 11;
else
AssertFatal(1==0,"Case for segmented PUCCH not yet implemented");
}
}
int rtimes100;
switch(*maxCodeRate){
case NR_PUCCH_MaxCodeRate_zeroDot08 :
rtimes100 = 8;
break;
case NR_PUCCH_MaxCodeRate_zeroDot15 :
rtimes100 = 15;
break;
case NR_PUCCH_MaxCodeRate_zeroDot25 :
rtimes100 = 25;
break;
case NR_PUCCH_MaxCodeRate_zeroDot35 :
rtimes100 = 35;
break;
case NR_PUCCH_MaxCodeRate_zeroDot45 :
rtimes100 = 45;
break;
case NR_PUCCH_MaxCodeRate_zeroDot60 :
rtimes100 = 60;
break;
case NR_PUCCH_MaxCodeRate_zeroDot80 :
rtimes100 = 80;
break;
default :
AssertFatal(1==0,"Invalid MaxCodeRate");
}
float r = (float)rtimes100/100;
if (O_csi == O_tot) {
if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r))
AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
r,O_tot,O_crc,nr_prbs);
else
return nr_prbs;
}
if (format==2){
// TODO fix this for multiple CSI reports
for (int i=1; i<=nr_prbs; i++){
if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) &&
(O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r))
return i;
}
AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs",
r,O_tot,O_crc,nr_prbs);
}
else{
AssertFatal(1==0,"Not yet implemented");
}
}
void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
dci_pdu_rel15_t *dci_pdu_rel15,
nr_dci_format_t format,
@@ -1608,6 +1685,20 @@ inline void add_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
*cur = UE_id;
}
/*
* Remove a UE from NR_UE_list listP
*/
inline int remove_nr_ue_list(NR_UE_list_t *listP, int UE_id) {
int *cur = &listP->head;
while (*cur != -1 && *cur != UE_id)
cur = &listP->next[*cur];
AssertFatal(*cur != -1, "UE %d not found in UE_list\n", UE_id);
int *next = &listP->next[*cur];
*cur = listP->next[*cur];
*next = -1;
return 1;
}
int find_nr_UE_id(module_id_t mod_idP, rnti_t rntiP)
//------------------------------------------------------------------------------
{
@@ -1686,15 +1777,21 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){
memset((void *) &UE_info->UE_sched_ctrl[UE_id],
0,
sizeof(NR_UE_sched_ctrl_t));
UE_info->UE_sched_ctrl[UE_id].ta_timer = 100;
UE_info->UE_sched_ctrl[UE_id].ta_frame = 0;
UE_info->UE_sched_ctrl[UE_id].ta_update = 31;
UE_info->UE_sched_ctrl[UE_id].ta_apply = false;
UE_info->UE_sched_ctrl[UE_id].ul_rssi = 0;
UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch *)malloc(num_slots_ul*sizeof(NR_sched_pucch));
UE_info->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch **)malloc(num_slots_ul*sizeof(NR_sched_pucch *));
for (int s=0; s<num_slots_ul;s++)
UE_info->UE_sched_ctrl[UE_id].sched_pucch[s] = (NR_sched_pucch *)malloc(2*sizeof(NR_sched_pucch));
UE_info->UE_sched_ctrl[UE_id].sched_pusch = (NR_sched_pusch *)malloc(num_slots_ul*sizeof(NR_sched_pusch));
for (int k=0; k<num_slots_ul; k++) {
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k],
0,
sizeof(NR_sched_pucch));
for (int l=0; l<2; l++)
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
0,
sizeof(NR_sched_pucch));
memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pusch[k],
0,
sizeof(NR_sched_pusch));
@@ -1733,9 +1830,11 @@ void mac_remove_nr_ue(module_id_t mod_id, rnti_t rnti)
/* UE found, remove it */
UE_id = i;
UE_info->num_UEs--;
UE_info->active[UE_id] = FALSE;
UE_info->rnti[UE_id] = 0;
remove_nr_ue_list(&UE_info->list, UE_id);
free(UE_info->UE_sched_ctrl[UE_id].sched_pucch);
free(UE_info->UE_sched_ctrl[UE_id].sched_pusch);
memset((void *) &UE_info->UE_sched_ctrl[UE_id],
@@ -1817,50 +1916,302 @@ void get_pdsch_to_harq_feedback(int Mod_idP,
}
}
uint16_t nr_get_csi_bitlen(int Mod_idP,
int UE_id,
uint8_t csi_report_id) {
uint16_t csi_bitlen =0;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
(CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
return csi_bitlen;
}
void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
int *period, int *offset) {
NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
switch(p_and_o){
case NR_CSI_ReportPeriodicityAndOffset_PR_slots4:
*period = 4;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots5:
*period = 5;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots8:
*period = 8;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots10:
*period = 10;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots16:
*period = 16;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots20:
*period = 20;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots40:
*period = 40;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots80:
*period = 80;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots160:
*period = 160;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160;
break;
case NR_CSI_ReportPeriodicityAndOffset_PR_slots320:
*period = 320;
*offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320;
break;
default:
AssertFatal(1==0,"No periodicity and offset resource found in CSI report");
}
}
//!TODO : same function can be written to handle csi_resources
void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) {
uint8_t csi_report_id = 0;
uint8_t csi_resourceidx =0;
uint8_t csi_ssb_idx =0;
NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement;
UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present;
for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId)
continue;
else {
//Finding the CSI_RS or SSB Resources
UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present;
if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){
struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB;
UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0;
UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0;
}
if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){
uint8_t nb_ssb_resources =0;
for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
*(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled ==
csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) {
if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
else
/*! From Spec 38.331
* nrofReportedRS
* The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
* capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
* When the field is absent the UE applies the value 1
*/
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1;
}else
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2;
nb_ssb_resources= csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
if (nb_ssb_resources){
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
}
else{
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0;
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0;
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0;
}
LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d",
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen,
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen,
UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen);
break ;
}
}
}
if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report){
AssertFatal(1==0,"Currently configuring only SSB beamreporting.");
}
break;
}
}
}
}
void nr_csi_meas_reporting(int Mod_idP,
int UE_id,
frame_t frame,
sub_frame_t slot,
int slots_per_tdd,
int ul_slots,
int n_slots_frame) {
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_sched_pucch *curr_pucch;
NR_PUCCH_ResourceSet_t *pucchresset;
NR_CSI_ReportConfig_t *csirep;
NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
int period, offset, sched_slot;
csi_period_offset(csirep,&period,&offset);
sched_slot = (period+offset)%n_slots_frame;
// prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
// preparation is done in first slot of tdd period
if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
// we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[sched_slot-slots_per_tdd+ul_slots][0];
NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
int found = -1;
pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
int n_list = pucchresset->resourceList.list.count;
for (int i=0; i<n_list; i++) {
if (*pucchresset->resourceList.list.array[i] == pucchcsires->pucch_Resource)
found = i;
}
AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
curr_pucch->resource_indicator = found;
n_list = pucch_Config->resourceToAddModList->list.count;
// going through the list of PUCCH resources to find the one indexed by resource_id
for (int i=0; i<n_list; i++) {
NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
switch(pucchres->format.present){
case NR_PUCCH_Resource__format_PR_format2:
if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
case NR_PUCCH_Resource__format_PR_format3:
if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
case NR_PUCCH_Resource__format_PR_format4:
if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
curr_pucch->simultaneous_harqcsi = false;
else
curr_pucch->simultaneous_harqcsi = true;
break;
default:
AssertFatal(1==0,"Invalid PUCCH format type");
}
}
}
curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
curr_pucch->frame = frame;
curr_pucch->ul_slot = sched_slot;
}
}
}
// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id) {
void nr_acknack_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id,
int *pucch_occ) {
NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
NR_sched_pucch *curr_pucch;
int first_ul_slot_tdd,k,i;
int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
uint8_t pdsch_to_harq_feedback[8];
int found = 0;
int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
nr_ulmix_slots++;
bool csi_pres=false;
for (k=0; k<nr_ulmix_slots; k++) {
if(UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
csi_pres=true;
}
// As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
// Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
if (csi_pres)
max_acknacks=10;
else
max_acknacks=2;
// this is hardcoded for now as ue specific
NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
// for each possible ul or mixed slot
for (k=0; k<nr_ulmix_slots; k++) {
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k];
// if there is free room in current pucch structure
if (curr_pucch->dai_c<MAX_ACK_BITS) {
curr_pucch->frame = frameP;
curr_pucch->dai_c++;
curr_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource
// first pucch occasion in first UL or MIXED slot
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
i = 0;
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) {
// computing slot in which pucch is scheduled
curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
curr_pucch->timing_indicator = i; // index in the list of timing indicators
*pucch_id = k;
return;
for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
//if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
// if there is free room in current pucch structure
if (curr_pucch->dai_c<max_acknacks) {
pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
if (pucch_res>-1){
curr_pucch->resource_indicator = pucch_res;
curr_pucch->frame = frameP;
// first pucch occasion in first UL or MIXED slot
first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
i = 0;
while (i<8 && found == 0) { // look if timing indicator is among allowed values
if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
found = 1;
if (found == 0) i++;
}
if (found == 1) {
// computing slot in which pucch is scheduled
curr_pucch->dai_c++;
curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
curr_pucch->timing_indicator = i; // index in the list of timing indicators
*pucch_id = k;
*pucch_occ = l;
return;
}
}
}
}
}
}
@@ -1868,6 +2219,22 @@ void nr_update_pucch_scheduling(int Mod_idP,
}
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
// to be updated later, for now simple implementation
// use the second allocation just in case there is csi in the first
// in that case use second resource (for a different symbol) see 9.2 in 38.213
if (l==1) {
if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
return -1;
else
return 1;
}
else
return 0;
}
void find_aggregation_candidates(uint8_t *aggregation_level,
uint8_t *nr_of_candidates,
NR_SearchSpace_t *ss) {
@@ -214,12 +214,8 @@ void nr_process_mac_pdu(
int UE_id = find_nr_UE_id(module_idP, rnti);
RC.nrmac[module_idP]->UE_info.mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_T(MAC, "[UE %d] First 32 bytes of DLSCH : \n", module_idP);
log_dump(MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n");
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){
mac_rlc_data_ind(module_idP,
@@ -322,40 +318,10 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
UE_info = &gNB_mac->UE_info;
int target_snrx10 = gNB_mac->pusch_target_snrx10;
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
// random access pusch with TC-RNTI
if (ra->state == WAIT_Msg3) {
if (sduP != NULL) { // if the CRC passed
if (ra->rnti != current_rnti) {
LOG_E(MAC,
"expected TC-RNTI %04x to match current RNTI %04x\n",
ra->rnti,
current_rnti);
return;
}
free(ra->preambles.preamble_list);
ra->state = RA_IDLE;
LOG_I(MAC, "reset RA state information for RA-RNTI %04x\n", ra->rnti);
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
UE_info->UE_beam_index[UE_id] = ra->beam_id;
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
bwpList->list.count);
const int bwp_id = 1;
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
LOG_I(MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
"adding UE MAC Context UE_id %d/RNTI %04x\n",
gnb_mod_idP,
current_rnti,
UE_id,
ra->rnti);
}
return;
if (sduP != NULL) {
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
}
if (UE_id != -1) {
@@ -385,6 +351,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
}
#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
LOG_I(MAC, "Printing received UL MAC payload at gNB side: %d \n");
for (int i = 0; i < sdu_lenP ; i++) {
//harq_process_ul_ue->a[i] = (unsigned char) rand();
@@ -392,6 +359,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
printf("%02x ",(unsigned char)sduP[i]);
}
printf("\n");
#endif
if (sduP != NULL){
@@ -401,6 +369,54 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
else {
}
}
}
} else {
if (!sduP) // check that CRC passed
return;
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
* and check the corresponding UE's RNTI match, in which case we activate
* it. */
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->state != WAIT_Msg3)
continue;
// random access pusch with TC-RNTI
if (ra->rnti != current_rnti) {
LOG_W(MAC,
"expected TC-RNTI %04x to match current RNTI %04x\n",
ra->rnti,
current_rnti);
continue;
}
const int UE_id = add_new_nr_ue(gnb_mod_idP, ra->rnti);
UE_info->secondaryCellGroup[UE_id] = ra->secondaryCellGroup;
compute_csi_bitlen(ra->secondaryCellGroup, UE_info, UE_id);
UE_info->UE_beam_index[UE_id] = ra->beam_id;
struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList;
AssertFatal(bwpList->list.count == 1,
"downlinkBWP_ToAddModList has %d BWP!\n",
bwpList->list.count);
const int bwp_id = 1;
UE_info->UE_sched_ctrl[UE_id].active_bwp = bwpList->list.array[bwp_id - 1];
LOG_I(MAC,
"[gNB %d][RAPROC] PUSCH with TC_RNTI %x received correctly, "
"adding UE MAC Context UE_id %d/RNTI %04x\n",
gnb_mod_idP,
current_rnti,
UE_id,
ra->rnti);
// re-initialize ta update variables afrer RA procedure completion
UE_info->UE_sched_ctrl[UE_id].ta_frame = frameP;
free(ra->preambles.preamble_list);
ra->state = RA_IDLE;
LOG_I(MAC,
"reset RA state information for RA-RNTI %04x/index %d\n",
ra->rnti,
i);
return;
}
}
}
+54 -44
View File
@@ -36,8 +36,6 @@
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#include "NR_TAG-Id.h"
#define MAX_ACK_BITS 2 //only format 0 is available for now
void set_cset_offset(uint16_t);
void mac_top_init_gNB(void);
@@ -82,7 +80,13 @@ void nr_schedule_ue_spec(module_id_t module_id,
sub_frame_t slot,
int num_slots_per_tdd);
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);
/* \brief default preprocessor */
void nr_simple_dlsch_preprocessor(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, uint8_t slots_per_frame);
/////// Random Access MAC-PHY interface functions and primitives ///////
@@ -126,42 +130,37 @@ uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs);
/////// Phy test scheduler ///////
/* \brief preprocessor for phytest: schedules UE_id 0 with fixed MCS on all
* freq resources */
void nr_preprocessor_phytest(module_id_t module_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
void nr_schedule_css_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t subframeP);
void nr_fill_nfapi_dl_pdu(int Mod_id,
int UE_id,
int bwp_id,
NR_SearchSpace_t *ss,
NR_ControlResourceSet_t *coreset,
nfapi_nr_dl_tti_request_body_t *dl_req,
rnti_t rnti,
NR_CellGroupConfig_t *secondaryCellGroup,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_sched_pucch *pucch_sched,
int nrOfLayers,
uint8_t mcs,
uint16_t rbSize,
uint16_t rbStart,
uint8_t numDmrsCdmGrpsNoData,
nfapi_nr_dmrs_type_e dmrsConfigType,
uint8_t table_idx,
uint16_t R,
uint8_t Qm,
uint32_t tbs,
int time_domain_assignment,
int StartSymbolIndex,
int NrOfSymbols,
uint8_t aggregation_level,
int CCEIndex,
int harq_pid,
int ndi,
int round);
int configure_fapi_dl_pdu_phytest(int Mod_id,
nfapi_nr_dl_tti_request_body_t *dl_req,
NR_sched_pucch *pucch_sched,
uint8_t *mcsIndex,
uint16_t *rbSize,
uint16_t *rbStart);
void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats);
void config_uldci(NR_BWP_Uplink_t *ubwp,
nfapi_nr_pusch_pdu_t *pusch_pdu,
@@ -171,20 +170,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,
int time_domain_assignment, uint8_t tpc,
int n_ubwp, int bwp_id);
void configure_fapi_dl_Tx(module_id_t Mod_idP,
frame_t frameP,
sub_frame_t slotP,
nfapi_nr_dl_tti_request_body_t *dl_req,
nfapi_nr_pdu_t *tx_req,
int tbs_bytes,
int16_t pdu_index);
void nr_schedule_uss_dlsch_phytest(module_id_t module_idP,
frame_t frameP,
sub_frame_t slotP,
NR_sched_pucch *pucch_sched,
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_config);
void nr_schedule_pusch(int Mod_idP,
int UE_id,
int num_slots_per_tdd,
@@ -198,12 +183,23 @@ void nr_schedule_pucch(int Mod_idP,
frame_t frameP,
sub_frame_t slotP);
void nr_update_pucch_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id);
void nr_csi_meas_reporting(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int ul_slots,
int n_slots_frame);
void nr_acknack_scheduling(int Mod_idP,
int UE_id,
frame_t frameP,
sub_frame_t slotP,
int slots_per_tdd,
int *pucch_id,
int *pucch_occ);
int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l);
void get_pdsch_to_harq_feedback(int Mod_idP,
int UE_id,
@@ -232,10 +228,11 @@ int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
NR_ServingCellConfigCommon_t *scc,
NR_BWP_Uplink_t *bwp,
uint16_t rnti,
uint8_t pucch_resource,
uint16_t O_uci,
uint16_t O_csi,
uint16_t O_ack,
uint8_t SR_flag);
uint8_t O_sr);
void find_search_space(int ss_type,
NR_BWP_Downlink_t *bwp,
@@ -320,6 +317,17 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
int m,
int nr_of_candidates);
uint16_t compute_pucch_prb_size(uint8_t format,
uint8_t nr_prbs,
uint16_t O_tot,
uint16_t O_csi,
NR_PUCCH_MaxCodeRate_t *maxCodeRate,
uint8_t Qm,
uint8_t n_symb,
uint8_t n_re_ctrl);
void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id);
int get_dlscs(nfapi_nr_config_request_t *cfg);
int get_ulscs(nfapi_nr_config_request_t *cfg);
@@ -366,6 +374,8 @@ int binomial(int n, int k);
bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot);
void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int CC_id);
/* \brief Function to indicate a received SDU on ULSCH.
@param Mod_id Instance ID of gNB
+5
View File
@@ -82,6 +82,11 @@ void mac_top_init_gNB(void)
RC.nrmac[i]->ul_handle = 0;
if (get_softmodem_params()->phy_test)
RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest;
else
RC.nrmac[i]->pre_processor_dl = nr_simple_dlsch_preprocessor;
}//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n");
+47 -5
View File
@@ -68,6 +68,9 @@
#include "LAYER2/NR_MAC_COMMON/nr_mac_common.h"
#include "NR_TAG.h"
#include <openair3/UICC/usim_interface.h>
/* Defs */
#define MAX_NUM_BWP 2
#define MAX_NUM_CORESET 2
@@ -188,9 +191,9 @@ typedef struct {
/// Template for RA computations
NR_RA_t ra[NR_NB_RA_PROC_MAX];
/// VRB map for common channels
uint8_t vrb_map[275];
uint16_t vrb_map[275];
/// VRB map for common channels and retransmissions by PHICH
uint8_t vrb_map_UL[275];
uint16_t vrb_map_UL[275];
/// number of subframe allocation pattern available for MBSFN sync area
uint8_t num_sf_allocation_pattern;
///Number of active SSBs
@@ -274,10 +277,12 @@ typedef struct UE_info {
typedef struct NR_sched_pucch {
int frame;
int ul_slot;
bool sr_flag;
int csi_bits;
bool simultaneous_harqcsi;
uint8_t dai_c;
uint8_t timing_indicator;
uint8_t resource_indicator;
bool active;
} NR_sched_pucch;
typedef struct NR_sched_pusch {
@@ -315,6 +320,25 @@ typedef struct NR_UE_ul_harq {
NR_UL_harq_states_t state;
} NR_UE_ul_harq_t;
typedef struct {
uint8_t nb_ssbri_cri;
uint8_t cri_ssbri_bitlen;
uint8_t rsrp_bitlen;
uint8_t diff_rsrp_bitlen;
}CRI_SSBRI_RSRP_bitlen_t;
#define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16
typedef struct nr_csi_report {
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type;
NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR CSI_Resource_type;
uint8_t nb_of_nzp_csi_report;
uint8_t nb_of_csi_ssb_report;
CRI_SSBRI_RSRP_bitlen_t CSI_report_bitlen[MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG];
} nr_csi_report_t;
/*! \brief scheduling control information set through an API */
typedef struct {
/// total amount of data awaiting for this UE
@@ -324,9 +348,10 @@ typedef struct {
/// the currently active BWP in DL
NR_BWP_Downlink_t *active_bwp;
NR_sched_pucch *sched_pucch;
NR_sched_pucch **sched_pucch;
/// selected PUCCH index, if scheduled
int pucch_sched_idx;
int pucch_occ_idx;
NR_sched_pusch *sched_pusch;
/// CCE index and aggregation, should be coherent with cce_list
@@ -350,7 +375,7 @@ typedef struct {
/// Retransmission-related information
NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
uint16_t ta_timer;
uint16_t ta_frame;
int16_t ta_update;
bool ta_apply;
uint8_t tpc0;
@@ -364,7 +389,11 @@ typedef struct {
} NR_UE_sched_ctrl_t;
typedef struct {
boolean_t fiveG_connected;
uicc_t *uicc;
} NRUEcontext_t;
typedef struct {
int lc_bytes_tx[64];
int lc_bytes_rx[64];
int dlsch_rounds[8];
@@ -377,6 +406,7 @@ typedef struct {
} NR_mac_stats_t;
/*! \brief UNR_E_list_t is a "list" of users within UE_info_t. Especial useful in
* the scheduler and to keep "classes" of users. */
typedef struct {
@@ -384,14 +414,18 @@ typedef struct {
int next[MAX_MOBILES_PER_GNB];
} NR_UE_list_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
#define MAX_CSI_REPORTCONFIG 48
typedef struct {
DLSCH_PDU DLSCH_pdu[4][MAX_MOBILES_PER_GNB];
/// scheduling control info
nr_csi_report_t csi_report_template[MAX_MOBILES_PER_GNB][MAX_CSI_REPORTCONFIG];
NR_UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_GNB];
NR_mac_stats_t mac_stats[MAX_MOBILES_PER_GNB];
NR_UE_list_t list;
int num_UEs;
bool active[MAX_MOBILES_PER_GNB];
rnti_t rnti[MAX_MOBILES_PER_GNB];
NR_CellGroupConfig_t *secondaryCellGroup[MAX_MOBILES_PER_GNB];
@@ -403,6 +437,11 @@ typedef struct {
uint8_t UE_beam_index[MAX_MOBILES_PER_GNB];
} NR_UE_info_t;
typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
frame_t frame,
sub_frame_t slot,
int num_slots_per_tdd);
/*! \brief top level eNB MAC structure */
typedef struct gNB_MAC_INST_s {
/// Ethernet parameters for northbound midhaul interface
@@ -465,6 +504,9 @@ typedef struct gNB_MAC_INST_s {
int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
/// current slot
int current_slot;
/// DL preprocessor for differentiated scheduling
nr_pp_impl_dl pre_processor_dl;
} gNB_MAC_INST;
#endif /*__LAYER2_NR_MAC_GNB_H__ */
+2 -12
View File
@@ -996,17 +996,7 @@ pdcp_data_ind(
* TODO: be sure of this
*/
if (NFAPI_MODE == NFAPI_UE_STUB_PNF ) {
#ifdef UESIM_EXPANSION
if (UE_NAS_USE_TUN) {
pdcpHead->inst = ctxt_pP->module_id;
} else {
pdcpHead->inst = 0;
}
#else
pdcpHead->inst = ctxt_pP->module_id;
#endif
} else { // nfapi_mode
if (UE_NAS_USE_TUN) {
pdcpHead->inst = ctxt_pP->module_id;
@@ -1035,7 +1025,7 @@ pdcp_data_ind(
pushNotifiedFIFO(&pdcp_sdu_list, new_sdu_p);
/* Print octets of incoming data in hexadecimal form */
LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
LOG_D(PDCP, "Following content has been received from RLC (%d,%d)(PDCP header has already been removed):\n",
sdu_buffer_sizeP - payload_offset + (int)sizeof(pdcp_data_ind_header_t),
sdu_buffer_sizeP - payload_offset);
//util_print_hex_octets(PDCP, &new_sdu_p->data[sizeof (pdcp_data_ind_header_t)], sdu_buffer_sizeP - payload_offset);
@@ -2287,7 +2277,7 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask ) {
nas_getparams();
if(UE_NAS_USE_TUN) {
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1;
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
netlink_init_tun("ue",num_if);
if (IS_SOFTMODEM_NOS1)
nas_config(1, 1, 2, "ue");
-3
View File
@@ -53,9 +53,6 @@ typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *cons
typedef boolean_t (*pdcp_data_ind_func_t)( const protocol_ctxt_t *, const srb_flag_t,
const MBMS_flag_t, const rb_id_t, const sdu_size_t,
mem_block_t *,const uint32_t *const, const uint32_t *const);
/* maximum number of tun interfaces that will be created to emulates UEs */
/* UEs beyond that will be multiplexed on the same tun */
#define MAX_NUMBER_NETIF 16
#define ENB_NAS_USE_TUN_W_MBMS_BIT (1<< 10)
#define PDCP_USE_NETLINK_BIT (1<< 11)
+3 -12
View File
@@ -86,12 +86,6 @@ extern struct msghdr nas_msg_rx;
#ifdef UESIM_EXPANSION
extern uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
#endif
# include "gtpv1u_eNB_task.h"
# include "gtpv1u_eNB_defs.h"
@@ -156,9 +150,9 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) {
nas_nlh_tx->nlmsg_len = sizeToWrite;
ret = sendmsg(nas_sock_fd[0],&nas_msg_tx,0);
} // PDCP_USE_NETLINK
AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]);
AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s), nas_sock_fd[0]: %d\n", errno, strerror(errno), nas_sock_fd[0]);
if( LOG_DEBUGFLAG(DEBUG_PDCP) )
log_dump(PDCP, pdcpData, min(sizeToWrite,30) , LOG_DUMP_CHAR,
"Printing first bytes of PDCP SDU before removing it from the list: \n");
@@ -202,6 +196,7 @@ int pdcp_fifo_flush_mbms_sdus(const protocol_ctxt_t *const ctxt_pP) {
//} // PDCP_USE_NETLINK
//AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno));
//AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno));
delNotifiedFIFO_elt (sdu_p);
pdcp_nb_sdu_sent ++;
@@ -503,11 +498,7 @@ int pdcp_fifo_read_input_sdus_fromnetlinksock (const protocol_ctxt_t *const ctx
}
} else { // ctxt.enb_flag => UE
if (NFAPI_MODE == NFAPI_UE_STUB_PNF) {
#ifdef UESIM_EXPANSION
ctxt.module_id = inst_pdcp_list[pdcp_read_header_g.inst];
#else
ctxt.module_id = pdcp_read_header_g.inst;
#endif
} else {
ctxt.module_id = 0;
}
+1 -1
View File
@@ -143,7 +143,7 @@ void (*rlc_rrc_data_conf)(
const protocol_ctxt_t *const ctxtP,
const rb_id_t rb_idP,
const mui_t muiP,
const rlc_tx_status_t statusP);
const rlc_tx_status_t statusP) __attribute__ ((aligned(32)));
typedef void (rrc_data_ind_cb_t)(
const protocol_ctxt_t *const ctxtP,
+8 -2
View File
@@ -19,6 +19,9 @@
* contact@openairinterface.org
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "nr_pdcp_ue_manager.h"
#include "NR_RadioBearerConfig.h"
#include "NR_RLC-BearerConfig.h"
@@ -43,6 +46,7 @@ static uint64_t pdcp_optmask;
/* rlc_data_req queue - begin */
/****************************************************************************/
#include <pthread.h>
/* NR PDCP and RLC both use "big locks". In some cases a thread may do
@@ -92,6 +96,7 @@ static void *rlc_data_req_thread(void *_)
{
int i;
pthread_setname_np(pthread_self(), "RLC queue");
while (1) {
if (pthread_mutex_lock(&q.m) != 0) abort();
while (q.length == 0)
@@ -203,6 +208,7 @@ static void *enb_tun_read_thread(void *_)
protocol_ctxt_t ctxt;
int rb_id = 1;
pthread_setname_np( pthread_self(),"enb_tun_read");
while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
@@ -247,7 +253,7 @@ static void *ue_tun_read_thread(void *_)
protocol_ctxt_t ctxt;
int rb_id = 1;
pthread_setname_np( pthread_self(),"ue_tun_read");
while (1) {
len = read(nas_sock_fd[0], &rx_buf, NL_MAX_PAYLOAD);
if (len == -1) {
@@ -368,7 +374,7 @@ uint64_t pdcp_module_init(uint64_t _pdcp_optmask)
nas_getparams();
if(UE_NAS_USE_TUN) {
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )?MAX_NUMBER_NETIF:1;
int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 )? MAX_MOBILES_PER_ENB : 1;
netlink_init_tun("ue",num_if);
//Add --nr-ip-over-lte option check for next line
if (IS_SOFTMODEM_NOS1)
@@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity,
*/
ret.sn_start = entity->rx_next;
ret.so_start = 0;
ret.next = cur;
goto set_end_different_sdu;
}
}
-12
View File
@@ -287,18 +287,6 @@ ue_ip_common_ip2wireless(
printk("[UE_IP_DRV][%s] Dest %d.%d.%d.%d\n",__FUNCTION__, dst_addr[0],dst_addr[1],dst_addr[2],dst_addr[3]);
}
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator start
#ifdef UESIM_EXPANSION
if ((src_addr[3] - 2)> instP) {
pdcph.inst = src_addr[3] - 2;
printk("[UE_IP_DRV] change INST from %d to %d\n",instP, pdcph.inst);
instP = src_addr[3] - 2;
priv_p=netdev_priv(ue_ip_dev[instP]);
}
#endif
// modify inst by IP address for the U-Plane of multiple UEs while L2 fapi simulator end
//get Ipv4 address and pass to PCDP header
printk("[UE_IP_DRV] source Id: 0x%08x\n",pdcph.sourceL2Id );
printk("[UE_IP_DRV] destinationL2Id Id: 0x%08x\n",pdcph.destinationL2Id );
+38
View File
@@ -79,6 +79,44 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) {
}
void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats, int target_snrx10) {
int num_ucis = UL_info->uci_ind.num_ucis;
nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list;
for (int i = 0; i < num_ucis; i++) {
switch (uci_list[i].pdu_type) {
case NFAPI_NR_UCI_PUSCH_PDU_TYPE: break;
case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: {
nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
if( (uci_pdu->pduBitmap>>1) & 0x01)
nr_rx_acknack(NULL,uci_pdu,NULL,UL_info,sched_ctrl,stats);
break;
}
case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: {
nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu = &uci_list[i].pucch_pdu_format_2_3_4;
// tpc (power control)
sched_ctrl->tpc1 = nr_get_tpc(target_snrx10,uci_pdu->ul_cqi,30);
if( (uci_pdu->pduBitmap>>1) & 0x01)
nr_rx_acknack(NULL,NULL,uci_pdu,UL_info,sched_ctrl,stats);
break;
}
}
}
UL_info->uci_ind.num_ucis = 0;
}
void handle_nr_ulsch(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
if(nfapi_mode == 1) {
+10 -3
View File
@@ -3295,7 +3295,10 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.present = LTE_MTC_SSB_NR_r15__periodicityAndOffset_r15_PR_sf20_r15;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.periodicityAndOffset_r15.choice.sf20_r15 = 0;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.measTimingConfig_r15.ssb_Duration_r15 = LTE_MTC_SSB_NR_r15__ssb_Duration_r15_sf4;
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30;
if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz120;
else
MeasObj2->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15 = LTE_RS_ConfigSSB_NR_r15__subcarrierSpacingSSB_r15_kHz30;
MeasObj2->measObject.choice.measObjectNR_r15.quantityConfigSet_r15 = 1;
MeasObj2->measObject.choice.measObjectNR_r15.ext1 = calloc(1, sizeof(struct LTE_MeasObjectNR_r15__ext1));
@@ -3306,7 +3309,11 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t
if (MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15 == NULL) exit(1);
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->present = LTE_MeasObjectNR_r15__ext1__bandNR_r15_PR_setup;
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78;
if (rrc_inst->nr_scg_ssb_freq > 2016666) //FR2
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 261;
else
MeasObj2->measObject.choice.measObjectNR_r15.ext1->bandNR_r15->choice.setup = 78;
ASN_SEQUENCE_ADD(&MeasObj_list->list, MeasObj2);
}
@@ -4020,7 +4027,6 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.buf[0] = 0;
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.size = 1;
MeasObj->measObject.choice.measObjectEUTRA.neighCellConfig.bits_unused = 6;
//<<<<<<< HEAD
MeasObj->measObject.choice.measObjectEUTRA.offsetFreq = NULL; // Default is 15 or 0dB
if (rrc_inst->carrier[0].sib1->tdd_Config!=NULL) {
@@ -4635,6 +4641,7 @@ rrc_eNB_process_MeasurementReport(
case 7:
LOG_D(RRC, "NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
printf("NR event frame %d subframe %d\n", ctxt_pP->frame, ctxt_pP->subframe);
break;
default:
+7 -1
View File
@@ -88,6 +88,12 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
}
/* TODO BCCH SIB1 SIBs */
if ((Srb_id & RAB_OFFSET ) == BCCH) {
memcpy(&buffer_pP[0],
RC.rrc[Mod_idP]->carrier[CC_id].SIB1_MBMS,
RC.rrc[Mod_idP]->carrier[CC_id].sizeof_SIB1_MBMS);
}
/* CCCH */
if( (Srb_id & RAB_OFFSET ) == CCCH) {
@@ -114,4 +120,4 @@ int8_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
return(0);
}
}
+31 -30
View File
@@ -200,6 +200,10 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) {
mib->message.choice.mib->spare.bits_unused = 7; // This makes a spare of 1 bits
mib->message.choice.mib->ssb_SubcarrierOffset = (carrier->ssb_SubcarrierOffset)&15;
/*
* The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables
* the reverse allocation is in nr_ue_decode_mib()
*/
mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero;
mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = *scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero;
AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n");
@@ -265,10 +269,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
gNB_RrcConfigurationReq *configuration
) {
asn_enc_rval_t enc_rval;
NR_BCCH_DL_SCH_Message_t *sib1_message ;
struct NR_SIB1 *sib1 ;
int i;
struct NR_PLMN_IdentityInfo nr_plmn_info;
// TODO : Add support for more than one PLMN
//int num_plmn = configuration->num_plmn;
@@ -276,31 +276,29 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
struct NR_PLMN_Identity nr_plmn[num_plmn];
NR_MCC_MNC_Digit_t nr_mcc_digit[num_plmn][3];
NR_MCC_MNC_Digit_t nr_mnc_digit[num_plmn][3];
memset(nr_plmn,0,sizeof(nr_plmn));
memset(nr_mcc_digit,0,sizeof(nr_mcc_digit));
memset(nr_mnc_digit,0,sizeof(nr_mnc_digit));
// struct NR_UAC_BarringInfoSet nr_uac_BarringInfoSet;
sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
memset(sib1_message,0,sizeof(NR_BCCH_DL_SCH_Message_t));
NR_BCCH_DL_SCH_Message_t *sib1_message = CALLOC(1,sizeof(NR_BCCH_DL_SCH_Message_t));
carrier->siblock1 = sib1_message;
sib1_message->message.present = NR_BCCH_DL_SCH_MessageType_PR_c1;
sib1_message->message.choice.c1 = CALLOC(1,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
memset(sib1_message->message.choice.c1,0,sizeof(struct NR_BCCH_DL_SCH_MessageType__c1));
sib1_message->message.choice.c1->present = NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1;
sib1_message->message.choice.c1->choice.systemInformationBlockType1 = CALLOC(1,sizeof(struct NR_SIB1));
sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1;
memset(sib1,0,sizeof(struct NR_SIB1));
struct NR_SIB1 *sib1 = sib1_message->message.choice.c1->choice.systemInformationBlockType1;
sib1->cellSelectionInfo = CALLOC(1,sizeof(struct NR_SIB1__cellSelectionInfo));
memset(sib1->cellSelectionInfo,0,sizeof(struct NR_SIB1__cellSelectionInfo));
sib1->cellSelectionInfo->q_RxLevMin = -50;
memset(&nr_plmn_info.plmn_IdentityList,0,sizeof(struct NR_PLMN_IdentityInfo__plmn_IdentityList));
asn_set_empty(&nr_plmn_info.plmn_IdentityList.list);
memset(&nr_plmn_info,0,sizeof(struct NR_PLMN_IdentityInfo));
memset(nr_plmn,0,num_plmn*sizeof(struct NR_PLMN_Identity));
for (i = 0; i < num_plmn; ++i) {
struct NR_PLMN_IdentityInfo *nr_plmn_info=CALLOC(1,sizeof(struct NR_PLMN_IdentityInfo));
asn_set_empty(&nr_plmn_info->plmn_IdentityList.list);
for (int i = 0; i < num_plmn; ++i) {
nr_mcc_digit[i][0] = (configuration->mcc[i]/100)%10;
nr_mcc_digit[i][1] = (configuration->mcc[i]/10)%10;
nr_mcc_digit[i][2] = (configuration->mcc[i])%10;
nr_plmn[i].mcc = CALLOC(1,sizeof(struct NR_MCC));
memset(nr_plmn[i].mcc,0,sizeof(struct NR_MCC));
asn_set_empty(&nr_plmn[i].mcc->list);
ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][0]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mcc->list, &nr_mcc_digit[i][1]);
@@ -308,26 +306,23 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
nr_mnc_digit[i][0] = (configuration->mnc[i]/100)%10;
nr_mnc_digit[i][1] = (configuration->mnc[i]/10)%10;
nr_mnc_digit[i][2] = (configuration->mnc[i])%10;
memset(&nr_plmn[i].mnc,0,sizeof(NR_MNC_t));
nr_plmn[i].mnc.list.size=0;
nr_plmn[i].mnc.list.count=0;
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][0]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][1]);
ASN_SEQUENCE_ADD(&nr_plmn[i].mnc.list, &nr_mnc_digit[i][2]);
ASN_SEQUENCE_ADD(&nr_plmn_info.plmn_IdentityList.list, &nr_plmn[i]);
ASN_SEQUENCE_ADD(&nr_plmn_info->plmn_IdentityList.list, &nr_plmn[i]);
}//end plmn loop
nr_plmn_info.cellIdentity.buf = MALLOC(8);
memset(nr_plmn_info.cellIdentity.buf,0,8);
nr_plmn_info.cellIdentity.buf[0]= (configuration->cell_identity >> 20) & 0xff;
nr_plmn_info.cellIdentity.buf[1]= (configuration->cell_identity >> 12) & 0xff;
nr_plmn_info.cellIdentity.buf[2]= (configuration->cell_identity >> 4) & 0xff;
nr_plmn_info.cellIdentity.buf[3]= (configuration->cell_identity << 4) & 0xff;
nr_plmn_info.cellIdentity.size= 4;
nr_plmn_info.cellIdentity.bits_unused= 4;
nr_plmn_info.cellReservedForOperatorUse = 0;
memset(&sib1->cellAccessRelatedInfo,0,sizeof(NR_CellAccessRelatedInfo_t));
ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, &nr_plmn_info);
nr_plmn_info->cellIdentity.buf = CALLOC(1,8);
nr_plmn_info->cellIdentity.buf[0]= (configuration->cell_identity >> 20) & 0xff;
nr_plmn_info->cellIdentity.buf[1]= (configuration->cell_identity >> 12) & 0xff;
nr_plmn_info->cellIdentity.buf[2]= (configuration->cell_identity >> 4) & 0xff;
nr_plmn_info->cellIdentity.buf[3]= (configuration->cell_identity << 4) & 0xff;
nr_plmn_info->cellIdentity.size= 4;
nr_plmn_info->cellIdentity.bits_unused= 4;
nr_plmn_info->cellReservedForOperatorUse = 0;
ASN_SEQUENCE_ADD(&sib1->cellAccessRelatedInfo.plmn_IdentityList.list, nr_plmn_info);
#if 0
sib1->uac_BarringInfo = CALLOC(1, sizeof(struct NR_SIB1__uac_BarringInfo));
memset(sib1->uac_BarringInfo, 0, sizeof(struct NR_SIB1__uac_BarringInfo));
@@ -340,11 +335,12 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
ASN_SEQUENCE_ADD(&sib1->uac_BarringInfo->uac_BarringInfoSetList, &nr_uac_BarringInfoSet);
#endif
//encode SIB1 to data
carrier->SIB1=(uint8_t *) malloc16(128);
enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_DL_SCH_Message,
NULL,
(void *)sib1_message,
carrier->SIB1,
100);
128);
AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
enc_rval.failed_type->name, enc_rval.encoded);
@@ -578,3 +574,8 @@ void do_SpCellConfig(gNB_RRC_INST *rrc,
spconfig->reconfigurationWithSync = CALLOC(1,sizeof(struct NR_ReconfigurationWithSync));
}
int do_DLInformationTransfer_NR (void * p) {
return 0;
}
+57
View File
@@ -0,0 +1,57 @@
/*
* 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
*
* Author and copyright: Laurent Thomas, open-cells.com
*
* 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
*/
#include <openair2/RRC/LTE/MESSAGES/asn1_msg.h>
#include <openair2/RRC/NR/nr_rrc_proto.h>
void rrc_gNB_process_NGAP_DOWNLINK_NAS (void ) {
do_DLInformationTransfer(0,NULL,0,0,NULL);
// send it as DL data
/*
rrc_data_req (
&ctxt,
srb_id,
(*rrc_eNB_mui)++,
SDU_CONFIRM_NO,
length,
buffer,
PDCP_TRANSMISSION_MODE_CONTROL);
*/
}
void rrc_gNB_send_NGAP_NAS_FIRST_REQ(void ) {
// We are noCore only now
// create message that should come from 5GC
// send it dow
rrc_gNB_process_NGAP_DOWNLINK_NAS();
}
void nr_rrc_rx_tx() {
// check timers
// check if UEs are lost, to remove them from upper layers
//
}
+1 -1
View File
@@ -93,7 +93,7 @@ int generate_CG_Config(gNB_RRC_INST *rrc,
int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m);
void nr_rrc_rx_tx(void);
/**\brief RRC eNB task.
\param void *args_p Pointer on arguments to start the task. */
+8 -4
View File
@@ -82,6 +82,7 @@
#include "executables/softmodem-common.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair2/X2AP/x2ap_eNB.h>
//#define XER_PRINT
@@ -178,10 +179,11 @@ void rrc_gNB_generate_SgNBAdditionRequestAcknowledge(
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
static void init_NR_SI(gNB_RRC_INST *rrc) {
static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration) {
LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__);
rrc->carrier.MIB = (uint8_t *) malloc16(4);
rrc->carrier.sizeof_MIB = do_MIB_NR(rrc,0);
rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration);
LOG_I(NR_RRC,"Done init_NR_SI\n");
rrc_mac_config_req_gNB(rrc->module_id,
rrc->carrier.ssb_SubcarrierOffset,
@@ -271,7 +273,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
rrc->carrier.pucch_TargetSNRx10 = configuration->pucch_TargetSNRx10;
/// System Information INIT
LOG_I(NR_RRC, PROTOCOL_NR_RRC_CTXT_FMT" Checking release \n",PROTOCOL_NR_RRC_CTXT_ARGS(&ctxt));
init_NR_SI(rrc);
init_NR_SI(rrc, configuration);
rrc_init_nr_global_param();
openair_nr_rrc_on(&ctxt);
return 0;
@@ -317,8 +319,10 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) {
MessageDef *msg;
/* send a tick to x2ap */
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
if (is_x2ap_enabled()){
msg = itti_alloc_new_message(TASK_RRC_ENB, X2AP_SUBFRAME_PROCESS);
itti_send_msg_to_task(TASK_X2AP, ctxt_pP->module_id, msg);
}
}
///---------------------------------------------------------------------------------------------------------------///
File diff suppressed because it is too large Load Diff
+1 -16
View File
@@ -6,6 +6,7 @@
#include <arpa/inet.h>
#define MAC_LTE_DLT 147
#define DLT_IPV4 228
/********************************************************/
/* Definitions and descriptions come from:
http://wiki.wireshark.org/Development/LibpcapFileFormat */
@@ -29,20 +30,4 @@ typedef struct pcaprec_hdr_s {
unsigned int orig_len; /* actual length of packet */
} pcaprec_hdr_t;
/* Context information for every MAC PDU that will be logged */
typedef struct MAC_Context_Info_t {
unsigned short radioType;
unsigned char direction;
unsigned char rntiType;
unsigned short rnti;
unsigned short ueid;
unsigned char isRetx;
unsigned char crcStatusOK;
unsigned short sysFrameNumber;
unsigned short subFrameNumber;
unsigned int subframesSinceCaptureStart;
} MAC_Context_Info_t;
#endif
+1 -1
View File
@@ -73,7 +73,7 @@ typedef guint8 gboolean;
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*---------------------------------------------------------------------------------------------------------------------------------------------*/
#define OPT_PARAMS_DESC { \
{"type" , CONFIG_HLP_TYPEMON, 0, strptr:&in_type, defstrval:"none", TYPE_STRING, 0}, \
{"type" , CONFIG_HLP_TYPEMON, 0, strptr:(char**)&in_type, defstrval:"none", TYPE_STRING, 0}, \
{"ip" , CONFIG_HLP_L2MONIP, 0, strptr:(char**)&in_ip, defstrval:"127.0.0.1", TYPE_STRING, 0}, \
{"path" , CONFIG_HLP_L2MONPATH, 0, strptr:(char**)&in_path,defstrval:"/tmp/oai_opt.pcap", TYPE_STRING, 0}, \
}
+108 -107
View File
@@ -90,6 +90,7 @@ what about the implementation
#include <pthread.h>
#include <stdint.h>
#include <sys/time.h>
#include "common/config/config_userapi.h"
#include "opt.h"
#include "common/utils/system.h"
@@ -99,8 +100,6 @@ int opt_enabled=0;
//static unsigned char g_PDUBuffer[1600];
//static unsigned int g_PDUOffset;
static char in_ip[128]={0};
static char in_path[128]={0};
FILE *file_fd = NULL;
pcap_hdr_t file_header = {
0xa1b2c3d4, /* magic number */
@@ -108,10 +107,14 @@ pcap_hdr_t file_header = {
0, /* timezone */
0, /* sigfigs - apparently all tools do this */
65535, /* snaplen - this should be long enough */
MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
DLT_IPV4
//MAC_LTE_DLT /* Data Link Type (DLT). Set as unused value 147 for now */
};
trace_mode_t opt_type = OPT_NONE;
static char *in_type=NULL;
static char *in_path=NULL;
static char *in_ip=NULL;
static unsigned int subframesSinceCaptureStart;
static int g_socksd = -1;/* UDP socket used for sending frames */
@@ -131,8 +134,80 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
guint8 oob_event, guint8 oob_event_value,
uint8_t *pdu_buffer, unsigned int pdu_buffer_size);
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
const unsigned char *PDU, unsigned int length);
unsigned short checksum(unsigned short *ptr, int length) {
int sum = 0;
u_short answer = 0;
unsigned short *w = ptr;
int nleft = length;
while(nleft > 1) {
sum += *w++;
nleft -= 2;
}
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
static int MAC_LTE_PCAP_WritePDU(const uint8_t *PDU,
unsigned int length) {
pcaprec_hdr_t packet_header;
// IPv4 header
typedef struct ip_hdr {
unsigned char ip_verlen; // 4-bit IPv4 version 4-bit header length (in 32-bit words)
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength; // Total length
unsigned short ip_id; // Unique identifier
unsigned short ip_offset; // Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR;
// Define the UDP header
typedef struct udp_hdr {
unsigned short src_portno; // Source port no.
unsigned short dst_portno; // Dest. port no.
unsigned short udp_length; // Udp packet length
unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR;
IPV4_HDR IPheader= {0};
IPheader.ip_verlen = (4 << 4) | (sizeof(IPV4_HDR) / sizeof(uint32_t));
IPheader.ip_totallength = htons(sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length);
IPheader.ip_ttl = 8; // Time-to-live is eight
IPheader.ip_protocol = IPPROTO_UDP;
IPheader.ip_srcaddr = inet_addr(in_ip);
IPheader.ip_destaddr = inet_addr(in_ip);
IPheader.ip_checksum = checksum((unsigned short *)&IPheader, sizeof(IPV4_HDR));
// Initialize the UDP header
UDP_HDR UDPheader;
UDPheader.src_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
UDPheader.dst_portno = htons( PACKET_MAC_LTE_DEFAULT_UDP_PORT);
UDPheader.udp_length = htons(sizeof(UDP_HDR) + length);
UDPheader.udp_checksum = 0;
/****************************************************************/
/* PCAP Header */
/* TODO: Timestamp might want to be relative to a more sensible
base time... */
struct timeval tv;
gettimeofday(&tv, NULL);
packet_header.ts_sec = tv.tv_sec;
packet_header.ts_usec = tv.tv_usec;
packet_header.incl_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
packet_header.orig_len =sizeof(IPV4_HDR) + sizeof(UDP_HDR) + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
fwrite(&IPheader, sizeof(IPV4_HDR), 1, file_fd);
fwrite(&UDPheader, sizeof(UDP_HDR), 1, file_fd);
fwrite(PDU, 1, length, file_fd);
fflush(file_fd);
return length;
}
static void *opt_listener_thread(void *arg) {
ssize_t ret;
@@ -198,7 +273,6 @@ int opt_create_listener_socket(char *ip_address, uint16_t port) {
}
threadCreate(&opt_listener.thread, opt_listener_thread, NULL, "flexran", -1, OAI_PRIORITY_RT_LOW);
return 0;
}
@@ -321,67 +395,20 @@ static void SendFrame(guint8 radioType, guint8 direction, guint8 rntiType,
frameOffset += pdu_buffer_size;
}
/* Send out the data over the UDP socket */
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
if ( opt_type == OPT_WIRESHARK )
/* Send out the data over the UDP socket */
bytesSent = sendto(g_socksd, frameBuffer, frameOffset, 0,
(const struct sockaddr *)&g_serv_addr, sizeof(g_serv_addr));
else
bytesSent = MAC_LTE_PCAP_WritePDU(frameBuffer, frameOffset);
if (bytesSent != frameOffset) {
LOG_W(OPT, "sendto() failed (not a thread-safe func)- expected %d bytes, got %ld (errno=%d)\n",
LOG_W(OPT, "trace_pdu expected %d bytes, got %ld (errno=%d)\n",
frameOffset, bytesSent, errno);
//exit(1);
}
}
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */
static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context,
const uint8_t *PDU,
unsigned int length)
{
pcaprec_hdr_t packet_header;
uint8_t context_header[256];
int offset = 0;
unsigned short tmp16;
/*****************************************************************/
/* Context information (same as written by UDP heuristic clients */
context_header[offset++] = context->radioType;
context_header[offset++] = context->direction;
context_header[offset++] = context->rntiType;
/* RNTI */
context_header[offset++] = MAC_LTE_RNTI_TAG;
tmp16 = htons(context->rnti);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* UEId */
context_header[offset++] = MAC_LTE_UEID_TAG;
tmp16 = htons(context->ueid);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* Subframe number */
context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG;
tmp16 = htons(context->subFrameNumber);
memcpy(context_header+offset, &tmp16, 2);
offset += 2;
/* CRC Status */
context_header[offset++] = MAC_LTE_CRC_STATUS_TAG;
context_header[offset++] = context->crcStatusOK;
/* Data tag immediately preceding PDU */
context_header[offset++] = MAC_LTE_PAYLOAD_TAG;
/****************************************************************/
/* PCAP Header */
/* TODO: Timestamp might want to be relative to a more sensible
base time... */
packet_header.ts_sec = context->subframesSinceCaptureStart / 1000;
packet_header.ts_usec = (context->subframesSinceCaptureStart % 1000) * 1000;
packet_header.incl_len = offset + length;
packet_header.orig_len = offset + length;
/***************************************************************/
/* Now write everything to the file */
fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd);
fwrite(context_header, 1, offset, file_fd);
fwrite(PDU, 1, length, file_fd);
return 1;
}
#include <common/ran_context.h>
extern RAN_CONTEXT_t RC;
#include <openair1/PHY/phy_extern_ue.h>
@@ -389,7 +416,6 @@ extern RAN_CONTEXT_t RC;
void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size,
int ueid, int rntiType, int rnti, uint16_t sysFrameNumber, uint8_t subFrameNumber, int oob_event,
int oob_event_value) {
MAC_Context_Info_t pdu_context;
int radioType=FDD_RADIO;
LOG_D(OPT,"sending packet to wireshark: direction=%s, size: %d, ueid: %d, rnti: %x, frame/sf: %d.%d\n",
direction?"DL":"UL", pdu_buffer_size, ueid, rnti, sysFrameNumber,subFrameNumber);
@@ -405,53 +431,41 @@ void trace_pdu_implementation(int direction, uint8_t *pdu_buffer, unsigned int p
switch (opt_type) {
case OPT_WIRESHARK :
if (g_socksd == -1) {
if (g_socksd == -1)
return;
}
SendFrame( radioType,
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
oob_event,oob_event_value,
pdu_buffer, pdu_buffer_size);
break;
case OPT_PCAP:
if (file_fd == NULL) {
if (file_fd == NULL)
return;
}
pdu_context.radioType = radioType;
pdu_context.direction = (direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK
: DIRECTION_UPLINK;
pdu_context.rntiType = rntiType;
pdu_context.rnti = rnti;
pdu_context.ueid = ueid;
pdu_context.isRetx = 0;
pdu_context.crcStatusOK =1;
pdu_context.sysFrameNumber = sysFrameNumber;
pdu_context.subFrameNumber = subFrameNumber;
pdu_context.subframesSinceCaptureStart = subframesSinceCaptureStart++;
MAC_LTE_PCAP_WritePDU( &pdu_context, pdu_buffer, pdu_buffer_size);
break;
case OPT_TSHARK:
default:
return;
break;
}
SendFrame( radioType,
(direction == DIRECTION_DOWNLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK,
rntiType, rnti, ueid, (sysFrameNumber<<4) + subFrameNumber,
1, 0, 1, //guint8 isPredefinedData, guint8 retx, guint8 crcStatus
oob_event,oob_event_value,
pdu_buffer, pdu_buffer_size);
}
/*---------------------------------------------------*/
int init_opt(void)
{
char *in_type=NULL;
int init_opt(void) {
in_type=malloc(200);
in_ip=malloc(200);
in_path=malloc(200);
paramdef_t opt_params[] = OPT_PARAMS_DESC ;
checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC;
uint16_t in_port=0;
config_set_checkfunctions(opt_params, opt_checkParams,
sizeof(opt_params)/sizeof(paramdef_t));
config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
subframesSinceCaptureStart = 0;
int tmptype = config_get_processedint( &(opt_params[OPTTYPE_IDX]));
@@ -462,25 +476,21 @@ int init_opt(void)
} else if (tmptype == OPT_PCAP && strlen(in_path) > 0) {
opt_type = OPT_PCAP;
opt_enabled=1;
LOG_I(OPT,"Enabling OPT for PCAP with the following file %s \n",in_path);
} else if (tmptype == OPT_WIRESHARK && strlen(in_ip) > 0) {
opt_enabled=1;
opt_type = OPT_WIRESHARK;
LOG_I(OPT,"Enabling OPT for wireshark for local interface %s\n",in_ip);
} else {
LOG_E(OPT,"Invalid OPT configuration\n");
config_printhelp(opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX);
}
in_port = PACKET_MAC_LTE_DEFAULT_UDP_PORT;
// trace_mode
switch (opt_type) {
case OPT_WIRESHARK:
LOG_I(OPT,"mode Wireshark: ip %s port %d\n", in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
/* Create local server socket only if using localhost address */
if (strcmp(in_ip, "127.0.0.1") == 0) {
opt_create_listener_socket(in_ip, in_port);
if (strncmp(in_ip, "127.0.0.1", 4) == 0) {
opt_create_listener_socket(in_ip, PACKET_MAC_LTE_DEFAULT_UDP_PORT);
}
g_socksd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -493,11 +503,12 @@ int init_opt(void)
/* Get remote IP address from the function argument */
g_serv_addr.sin_family = AF_INET;
g_serv_addr.sin_port = htons(in_port);
g_serv_addr.sin_port = htons(PACKET_MAC_LTE_DEFAULT_UDP_PORT);
g_serv_addr.sin_addr.s_addr = inet_addr(in_ip);
break;
case OPT_PCAP:
LOG_I(OPT,"mode PCAB : path is %s \n",in_path);
file_fd = fopen(in_path, "w");
if (file_fd == NULL) {
@@ -516,19 +527,9 @@ int init_opt(void)
default:
opt_type = OPT_NONE;
LOG_W(OPT, "supported Option\n");
LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type);
break;
}
if ( opt_type == OPT_WIRESHARK )
LOG_E(OPT,"mode Wireshark: ip %s port %d\n", in_ip, in_port);
else if (opt_type == OPT_PCAP)
LOG_E(OPT,"mode PCAB : path is %s \n",in_path);
else
LOG_E(OPT,"Unsupported or unknown mode %d \n", opt_type);
// mac_info = (mac_info*)malloc16(sizeof(mac_lte_info));
// memset(mac_info, 0, sizeof(mac_lte_info)+pdu_buffer_size + 8);
return (1);
}