diff --git a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-cu.sa.f1.conf similarity index 87% rename from ci-scripts/conf_files/gnb-cu.sa.band78.106prb.usrpb200.conf rename to ci-scripts/conf_files/gnb-cu.sa.f1.conf index 3d716c81efeb41af9933f725d64009fa5019ca56..c419979a96b7cf2ad4821bd93235d8a0f90a2f79 100644 --- a/ci-scripts/conf_files/gnb-cu.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-cu.sa.f1.conf @@ -78,12 +78,8 @@ security = { log_config : { global_log_level ="info"; - hw_log_level ="info"; - phy_log_level ="info"; - mac_log_level ="info"; - rlc_log_level ="debug"; pdcp_log_level ="info"; rrc_log_level ="info"; - f1ap_log_level ="debug"; - ngap_log_level ="debug"; + f1ap_log_level ="info"; + ngap_log_level ="info"; }; diff --git a/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf new file mode 100644 index 0000000000000000000000000000000000000000..ed4a1da547fcf128ead7d355099f03bcc7966900 --- /dev/null +++ b/ci-scripts/conf_files/gnb-du.sa.band1.52prb.usrpb210.conf @@ -0,0 +1,218 @@ +Active_gNBs = ( "gNB-Eurecom-DU"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_DU_ID = 0xe00; + +# cell_type = "CELL_MACRO_GNB"; + + gNB_name = "gNB-Eurecom-DU"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 222; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1, sd = 0xffffff }) }); + + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + min_rxtxtime = 6; + + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 423130; + dl_frequencyBand = 1; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 422194; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 0; + dl_carrierBandwidth = 52; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 14025; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 0; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 7; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 1; + ul_absoluteFrequencyPointA = 384194; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 0; + ul_carrierBandwidth = 52; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 14025; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 0; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 12; + preambleReceivedTargetPower = -90; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 3; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 15; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 0, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -70; + n_TimingAdvanceOffset = 0; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 0; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 0; + ssPBCH_BlockPower = -25; + } + + ); + + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + } +); + +MACRLCs = ( + { + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "f1"; + local_n_if_name = "eth0"; + local_n_address = "192.168.68.195"; + remote_n_address = "192.168.68.194"; + local_n_portc = 500; + local_n_portd = 2153; + remote_n_portc = 501; + remote_n_portd = 2153; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 1; + } +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 200; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + # The higher att for TX than RX is because we use a circulator (as for TDD), + # while we should use a duplexer in the FDD case. However, it uses the same setup. + att_tx = 18 + att_rx = 0; + bands = [1]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 108; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; + } +); + +THREAD_STRUCT = ( + { + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; + } +); + +log_config : { + global_log_level = "info"; +}; diff --git a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml index 1f28fce309018f22fe91eacd0053b9fd22b08bf3..e473fdea10a51381003dfe19b3b13157fbb2d427 100644 --- a/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_f1_b200_quectel.xml @@ -22,7 +22,7 @@ --> <testCaseList> <htmlTabRef>TEST-SA-FR1-F1-B200</htmlTabRef> - <htmlTabName>40 MHz TDD F1 SA</htmlTabName> + <htmlTabName>10 MHz FDD F1 SA</htmlTabName> <htmlTabIcon>tasks</htmlTabIcon> <repeatCount>1</repeatCount> <TestCaseRequestedList> @@ -89,11 +89,11 @@ <testCase id="130102"> <class>Deploy_Object</class> - <desc>Deploy gNB-DU (TDD/Band78/40MHz/B200) in a container</desc> + <desc>Deploy gNB-DU (FDD/Band1/10MHz/B200) in a container</desc> <yaml_path>ci-scripts/yaml_files/sa_f1_b200_gnb</yaml_path> <eNB_instance>0</eNB_instance> <eNB_serverId>0</eNB_serverId> - <services>gnb_du_tdd</services> + <services>gnb_du_fdd</services> </testCase> <testCase id="100000"> @@ -159,8 +159,8 @@ <testCase id="170000"> <class>Iperf</class> - <desc>iperf (DL/80Mbps/UDP)(30 sec)</desc> - <iperf_args>-u -b 80M -t 30 -i 1 -fm</iperf_args> + <desc>iperf (DL/50Mbps/UDP)(30 sec)</desc> + <iperf_args>-u -b 50M -t 30 -i 1 -fm</iperf_args> <direction>DL</direction> <id>idefix</id> <iperf_packetloss_threshold>10</iperf_packetloss_threshold> @@ -170,8 +170,8 @@ <testCase id="170001"> <class>Iperf</class> - <desc>iperf (UL/8Mbps/UDP)(30 sec)</desc> - <iperf_args>-u -b 8M -t 30 -i 1 -fm</iperf_args> + <desc>iperf (UL/25Mbps/UDP)(30 sec)</desc> + <iperf_args>-u -b 25M -t 30 -i 1 -fm</iperf_args> <direction>UL</direction> <id>idefix</id> <iperf_packetloss_threshold>1</iperf_packetloss_threshold> @@ -181,8 +181,8 @@ <testCase id="170002"> <class>Iperf</class> - <desc>iperf (BIDIR TCP)(20 sec)(single-ue profile)</desc> - <iperf_args>-t 20 --bidir</iperf_args> + <desc>iperf (BIDIR TCP)(60 sec)(single-ue profile)</desc> + <iperf_args>-t 60 --bidir</iperf_args> <direction>BIDIR</direction> <id>idefix</id> <iperf_profile>single-ue</iperf_profile> diff --git a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml index 2ad0818a4777a0f1071a591fa63163c68d5d6378..072461af5cd1aee294cd846e81f6a25ef0ff7a20 100644 --- a/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml +++ b/ci-scripts/yaml_files/sa_f1_b200_gnb/docker-compose.yml @@ -8,7 +8,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --sa --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function volumes: - - ../../conf_files/gnb-cu.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb-cu.sa.f1.conf:/opt/oai-gnb/etc/gnb.conf networks: public_net: ipv4_address: 192.168.68.194 @@ -20,15 +20,15 @@ services: timeout: 5s retries: 5 - gnb_du_tdd: + gnb_du_fdd: image: oai-gnb:latest privileged: true container_name: sa-du-b200-gnb environment: USE_B2XX: 'yes' - USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx -E --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 1 --RUs.[0].att_rx 18 --RUs.[0].att_tx 18 + USE_ADDITIONAL_OPTIONS: --sa --RUs.[0].sdr_addrs serial=30C51D4 --telnetsrv --telnetsrv.shrmod ci --log_config.global_log_options level,nocolor,time,line_num,function --gNBs.[0].min_rxtxtime 2 --gNBs.[0].do_CSIRS 1 --gNBs.[0].do_SRS 0 --MACRLCs.[0].ul_max_mcs 28 --L1s.[0].max_ldpc_iterations 20 volumes: - - ../../conf_files/gnb-du.sa.band78.106prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb-du.sa.band1.52prb.usrpb210.conf:/opt/oai-gnb/etc/gnb.conf - /dev:/dev networks: public_net: diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index ea879e93b40f810f56a695eb83ed88766ccaf429..ea6c8b860e3937031394f693da45a30e73a513c4 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -43,6 +43,7 @@ #define NR_NB_REG_PER_CCE 6 #define NR_NB_SC_PER_RB 12 #define NR_MAX_NUM_LCID 32 +#define NR_MAX_NUM_QFI 64 typedef enum { nr_FR1 = 0, diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c index 4c2e82dc643c0287224c92c4b919e492b4466c23..d04dde62e72372151a98dc2e8ef049065f1666c5 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c @@ -30,27 +30,27 @@ const uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits) uint8_t temp1[crcPolynomialSize], temp2[crcPolynomialSize]; uint8_t **crc_generator_matrix = malloc(payloadSizeBits*sizeof(uint8_t *) + payloadSizeBits*crcPolynomialSize*sizeof(uint8_t)); - if (crc_generator_matrix) - for (int i = 0; i < payloadSizeBits; i++) - crc_generator_matrix[i] = ((uint8_t*)&crc_generator_matrix[payloadSizeBits])+i*crcPolynomialSize; + if (crc_generator_matrix) + for (int i = 0; i < payloadSizeBits; i++) + crc_generator_matrix[i] = ((uint8_t *)&crc_generator_matrix[payloadSizeBits]) + i * crcPolynomialSize; - for (int i = 0; i < crcPolynomialSize; i++) - crc_generator_matrix[payloadSizeBits-1][i]=crcPolynomialPattern[i+1]; + for (int i = 0; i < crcPolynomialSize; i++) + crc_generator_matrix[payloadSizeBits - 1][i] = crcPolynomialPattern[i + 1]; - for (int i = payloadSizeBits-2; i >= 0; i--){ + for (int i = payloadSizeBits - 2; i >= 0; i--) { for (int j = 0; j < crcPolynomialSize-1; j++) temp1[j]=crc_generator_matrix[i+1][j+1]; - temp1[crcPolynomialSize-1]=0; + temp1[crcPolynomialSize - 1] = 0; - for (int j = 0; j < crcPolynomialSize; j++) - temp2[j]=crc_generator_matrix[i+1][0]*crcPolynomialPattern[j+1]; + for (int j = 0; j < crcPolynomialSize; j++) + temp2[j] = crc_generator_matrix[i + 1][0] * crcPolynomialPattern[j + 1]; - for (int j = 0; j < crcPolynomialSize; j++){ + for (int j = 0; j < crcPolynomialSize; j++) { if(temp1[j]+temp2[j] == 1) crc_generator_matrix[i][j]=1; else crc_generator_matrix[i][j]=0; - } - } + } + } return (const uint8_t **)crc_generator_matrix; } diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c index 18de88db79f01d222c860e2a984457a0507abcff..06c852a7dd936beb0f9509a9d31e3dea569e37f4 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoder.c @@ -28,7 +28,7 @@ * \email raymond.knopp@eurecom.fr, turker.yilmaz@eurecom.fr * \note * \warning -*/ + */ /* * Return values: @@ -68,13 +68,13 @@ int8_t polar_decoder(double *input, { t_nrPolar_params *polarParams=nr_polar_params(messageType, messageLength, aggregation_level, true); //Assumes no a priori knowledge. - uint8_t bit[polarParams->N][polarParams->n+1][2*listSize]; - memset(bit,0,sizeof bit); + uint8_t bit[polarParams->N][polarParams->n + 1][2 * listSize]; + memset(bit, 0, sizeof bit); uint8_t bitUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True memset(bitUpdated,0,sizeof bitUpdated); uint8_t llrUpdated[polarParams->N][polarParams->n+1]; //0=False, 1=True memset(llrUpdated,0,sizeof llrUpdated); - double llr[polarParams->N][polarParams->n+1][2*listSize]; + double llr[polarParams->N][polarParams->n + 1][2 * listSize]; uint8_t crcChecksum[polarParams->crcParityBits][2*listSize]; memset(crcChecksum,0,sizeof crcChecksum); double pathMetric[2*listSize]; @@ -127,7 +127,8 @@ int8_t polar_decoder(double *input, double d_tilde[polarParams->N]; nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); - for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + for (int j = 0; j < polarParams->N; j++) + llr[j][polarParams->n][0] = d_tilde[j]; /* * SCL polar decoder. @@ -139,48 +140,56 @@ int8_t polar_decoder(double *input, uint8_t listIndex[2*listSize], copyIndex; for (uint16_t currentBit=0; currentBit<polarParams->N; currentBit++) { - updateLLR(currentListSize, currentBit, 0, polarParams->N, polarParams->n+1, 2*listSize, llr, llrUpdated, bit, bitUpdated); + updateLLR(currentListSize, currentBit, 0, polarParams->N, polarParams->n + 1, 2 * listSize, llr, llrUpdated, bit, bitUpdated); if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. - updatePathMetric(pathMetric, currentListSize, 0, currentBit, polarParams->N, polarParams->n+1, 2*listSize, llr); + updatePathMetric(pathMetric, currentListSize, 0, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr); } else { //Information or CRC bit. - updatePathMetric2(pathMetric, currentListSize, currentBit, polarParams->N, polarParams->n+1, 2*listSize, llr); + updatePathMetric2(pathMetric, currentListSize, currentBit, polarParams->N, polarParams->n + 1, 2 * listSize, llr); for (int i = 0; i < currentListSize; i++) { - for (int j = 0; j < polarParams->N; j++) { - for (int k = 0; k < (polarParams->n+1); k++) { - bit[j][k][i+currentListSize]=bit[j][k][i]; - llr[j][k][i+currentListSize]=llr[j][k][i]; + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n + 1); k++) { + bit[j][k][i + currentListSize] = bit[j][k][i]; + llr[j][k][i + currentListSize] = llr[j][k][i]; } - } + } } - for (int i = 0; i < currentListSize; i++) { - bit[currentBit][0][i]=0; - crcState[i+currentListSize]=crcState[i]; - } - - for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; - - bitUpdated[currentBit][0]=1; - updateCrcChecksum2(polarParams->crcParityBits, 2*listSize, crcChecksum, - polarParams->K, polarParams->crcParityBits, extended_crc_generator_matrix, - currentListSize, nonFrozenBit, polarParams->crcParityBits); - currentListSize*=2; + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i] = 0; + crcState[i + currentListSize] = crcState[i]; + } - //Keep only the best "listSize" number of entries. + for (int i = currentListSize; i < 2 * currentListSize; i++) + bit[currentBit][0][i] = 1; + + bitUpdated[currentBit][0] = 1; + updateCrcChecksum2(polarParams->crcParityBits, + 2 * listSize, + crcChecksum, + polarParams->K, + polarParams->crcParityBits, + extended_crc_generator_matrix, + currentListSize, + nonFrozenBit, + polarParams->crcParityBits); + currentListSize *= 2; + + // Keep only the best "listSize" number of entries. if (currentListSize > listSize) { - for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + for (uint8_t i = 0; i < 2 * listSize; i++) + listIndex[i] = i; nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); - //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + // sort listIndex[listSize, ..., 2*listSize-1] in descending order. uint8_t swaps, tempInd; for (uint8_t i = 0; i < listSize; i++) { swaps = 0; - for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { - if (listIndex[j+1] > listIndex[j]) { + for (uint8_t j = listSize; j < (2 * listSize - i) - 1; j++) { + if (listIndex[j + 1] > listIndex[j]) { tempInd = listIndex[j]; listIndex[j] = listIndex[j + 1]; listIndex[j + 1] = tempInd; @@ -196,8 +205,8 @@ int8_t polar_decoder(double *input, for (int k=(listSize-1); k>0; k--) { for (int i=0; i<polarParams->N; i++) { for (int j=0; j<(polarParams->n+1); j++) { - bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; - llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + bit[i][j][listIndex[(2 * listSize - 1) - k]] = bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2 * listSize - 1) - k]] = llr[i][j][listIndex[k]]; } } } @@ -285,7 +294,8 @@ int8_t polar_decoder(double *input, for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { if ( crcState[listIndex[i]] == 1 ) { - for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]]; + for (int j = 0; j < polarParams->N; j++) + polarParams->nr_polar_U[j] = bit[j][0][listIndex[i]]; //Extract the information bits (û to ĉ) nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N); @@ -626,7 +636,7 @@ uint32_t polar_decoder_int16(int16_t *input, printf("\n"); #endif - int16_t d_tilde[polarParams->N];// = malloc(sizeof(double) * polarParams->N); + int16_t d_tilde[polarParams->N]; nr_polar_rate_matching_int16(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength, polarParams->i_bil); for (int i=0; i<polarParams->N; i++) { @@ -687,14 +697,9 @@ uint32_t polar_decoder_int16(int16_t *input, uint64_t B[4] = {0}; if (polarParams->K<65) { - B[0] = polarParams->B_tab0[0][Cprimebyte[0]] | - polarParams->B_tab0[1][Cprimebyte[1]] | - polarParams->B_tab0[2][Cprimebyte[2]] | - polarParams->B_tab0[3][Cprimebyte[3]] | - polarParams->B_tab0[4][Cprimebyte[4]] | - polarParams->B_tab0[5][Cprimebyte[5]] | - polarParams->B_tab0[6][Cprimebyte[6]] | - polarParams->B_tab0[7][Cprimebyte[7]]; + B[0] = polarParams->B_tab0[0][Cprimebyte[0]] | polarParams->B_tab0[1][Cprimebyte[1]] | polarParams->B_tab0[2][Cprimebyte[2]] + | polarParams->B_tab0[3][Cprimebyte[3]] | polarParams->B_tab0[4][Cprimebyte[4]] | polarParams->B_tab0[5][Cprimebyte[5]] + | polarParams->B_tab0[6][Cprimebyte[6]] | polarParams->B_tab0[7][Cprimebyte[7]]; } else if (polarParams->K<129) { int len = polarParams->K/8; diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c index 6ae6c46498cd197122799e9bcb6c3df502912d2d..5a4374351a6ffc2b8908ed30c9f9fd2aacd80959 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -45,20 +45,23 @@ static inline void updateBit(uint8_t listSize, uint8_t bit[xlen][ylen][zlen], uint8_t bitU[xlen][ylen]) { - uint16_t offset = ( xlen/(pow(2,(ylen-col))) ); - - for (uint8_t i=0; i<listSize; i++) { - if (( (row) % (2*offset) ) >= offset ) { - if (bitU[row][col-1]==0) updateBit(listSize, row, (col-1), xlen, ylen, zlen, bit, bitU); - bit[row][col][i] = bit[row][col-1][i]; - } else { - if (bitU[row][col-1]==0) updateBit(listSize, row, (col-1), xlen, ylen, zlen, bit, bitU); - if (bitU[row+offset][col-1]==0) updateBit(listSize, (row+offset), (col-1), xlen, ylen, zlen, bit, bitU); - bit[row][col][i] = ( (bit[row][col-1][i]+bit[row+offset][col-1][i]) % 2); - } - } + uint16_t offset = (xlen / (pow(2, (ylen - col)))); + + for (uint8_t i = 0; i < listSize; i++) { + if (((row) % (2 * offset)) >= offset) { + if (bitU[row][col - 1] == 0) + updateBit(listSize, row, (col - 1), xlen, ylen, zlen, bit, bitU); + bit[row][col][i] = bit[row][col - 1][i]; + } else { + if (bitU[row][col - 1] == 0) + updateBit(listSize, row, (col - 1), xlen, ylen, zlen, bit, bitU); + if (bitU[row + offset][col - 1] == 0) + updateBit(listSize, (row + offset), (col - 1), xlen, ylen, zlen, bit, bitU); + bit[row][col][i] = ((bit[row][col - 1][i] + bit[row + offset][col - 1][i]) % 2); + } + } - bitU[row][col]=1; + bitU[row][col] = 1; } static inline void computeLLR(uint16_t row, @@ -75,35 +78,38 @@ static inline void computeLLR(uint16_t row, llr[row][col][i] = log((exp(a + b) + 1) / (exp(a) + exp(b))); //eq. (8a) } - void updateLLR(uint8_t listSize, - uint16_t row, - uint16_t col, - uint16_t xlen, - uint8_t ylen, - int zlen, - double llr[xlen][ylen][zlen], - uint8_t llrU[xlen][ylen], - uint8_t bit[xlen][ylen][zlen], - uint8_t bitU[xlen][ylen] - ) + uint16_t row, + uint16_t col, + uint16_t xlen, + uint8_t ylen, + int zlen, + double llr[xlen][ylen][zlen], + uint8_t llrU[xlen][ylen], + uint8_t bit[xlen][ylen][zlen], + uint8_t bitU[xlen][ylen]) { - uint16_t offset = (xlen/(pow(2,(ylen-col-1)))); - for (uint8_t i=0; i<listSize; i++) { - if (( (row) % (2*offset) ) >= offset ) { - if(bitU[row-offset][col]==0) updateBit(listSize, (row-offset), col, xlen, ylen, zlen, bit, bitU); - if(llrU[row-offset][col+1]==0) updateLLR(listSize, (row-offset), (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU ); - if(llrU[row][col+1]==0) updateLLR(listSize, row, (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU); - llr[row][col][i] = (pow((-1),bit[row-offset][col][i])*llr[row-offset][col+1][i]) + llr[row][col+1][i]; - } else { - if(llrU[row][col+1]==0) updateLLR(listSize, row, (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU ); - if(llrU[row+offset][col+1]==0) updateLLR(listSize, (row+offset), (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU ); - computeLLR(row, col, i, offset, xlen, ylen, zlen, llr); - } - } - llrU[row][col]=1; + uint16_t offset = (xlen / (pow(2, (ylen - col - 1)))); + for (uint8_t i = 0; i < listSize; i++) { + if ((row % (2 * offset)) >= offset) { + if (bitU[row - offset][col] == 0) + updateBit(listSize, (row - offset), col, xlen, ylen, zlen, bit, bitU); + if (llrU[row - offset][col + 1] == 0) + updateLLR(listSize, (row - offset), (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU); + if (llrU[row][col + 1] == 0) + updateLLR(listSize, row, (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU); + llr[row][col][i] = (pow((-1), bit[row - offset][col][i]) * llr[row - offset][col + 1][i]) + llr[row][col + 1][i]; + } else { + if (llrU[row][col + 1] == 0) + updateLLR(listSize, row, (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU); + if (llrU[row + offset][col + 1] == 0) + updateLLR(listSize, (row + offset), (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU); + computeLLR(row, col, i, offset, xlen, ylen, zlen, llr); + } + } + llrU[row][col] = 1; - // printf("LLR (a %f, b %f): llr[%d][%d] %f\n",32*a,32*b,col,row,32*llr[col][row]); + // printf("LLR (a %f, b %f): llr[%d][%d] %f\n",32*a,32*b,col,row,32*llr[col][row]); } void updatePathMetric(double *pathMetric, diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index e48a2058895de0e3c44fe6b65ef8a56526b7c0f7..490b24860db709f2147fe10786613937a0caf3b3 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -112,7 +112,7 @@ struct nrPolar_params { const uint8_t **crc_generator_matrix; // G_P const uint8_t **G_N; - uint64_t **G_N_tab; + fourDimArray_t *G_N_tab; int groupsize; int *rm_tab; uint64_t cprime_tab0[32][256]; @@ -219,9 +219,7 @@ uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max); -void nr_polar_channel_interleaver_pattern(uint16_t *cip, - uint8_t I_BIL, - uint16_t E); +void nr_polar_channel_interleaver_pattern(uint16_t *cip, const uint8_t I_BIL, const uint16_t E); void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, @@ -258,7 +256,7 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, const uint16_t *Q_0_Nminus1, uint16_t K, uint16_t N, - uint16_t E, + const uint16_t E, uint8_t n_PC, uint8_t n_pc_wm); @@ -284,7 +282,7 @@ void nr_polar_generate_u(uint64_t *u, uint16_t N, uint8_t n_pc); -void nr_polar_uxG(uint64_t *D, const uint64_t *u, const uint64_t **G_N_tab, uint16_t N); +void nr_polar_uxG(uint64_t *D, const uint64_t *u, const fourDimArray_t *G_N_tab, uint16_t N); void nr_polar_info_extraction_from_u(uint64_t *Cprime, const uint8_t *u, diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c index ea476c0d3871c646f75126a3356a8e8d6f203852..0a5982049b802ba68b321cd0a606e8ae3f76a5d7 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c @@ -359,15 +359,11 @@ void build_polar_tables(t_nrPolar_params *polarParams) { AssertFatal(polarParams->K > 17, "K = %d < 18, is not possible\n",polarParams->K); AssertFatal(polarParams->K < 129, "K = %d > 128, is not supported yet\n",polarParams->K); int bit_i,ip; - int numbytes = polarParams->K>>3; - int residue = polarParams->K&7; - int numbits; - - if (residue>0) numbytes++; + const int numbytes = (polarParams->K+7)/8; + const int residue = polarParams->K&7; for (int byte=0; byte<numbytes; byte++) { - if (byte<(polarParams->K>>3)) numbits=8; - else numbits=residue; + int numbits = byte<(polarParams->K>>3) ? 8 : residue; for (int val=0; val<256; val++) { polarParams->cprime_tab0[byte][val] = 0; @@ -388,16 +384,20 @@ void build_polar_tables(t_nrPolar_params *polarParams) { AssertFatal(polarParams->N == 512 || polarParams->N == 256 || polarParams->N == 128 || polarParams->N == 64, "N = %d, not done yet\n", polarParams->N); // build G bit vectors for information bit positions and convert the bit as bytes tables in nr_polar_kronecker_power_matrices.c to - // 64 bit packed vectors. - polarParams->G_N_tab = (uint64_t **)calloc(polarParams->N, sizeof(int64_t *)); - + // 64 bit packed vectors. + // Truncates id N%64 != 0 + allocCast2D(pp, uint64_t, polarParams->G_N_tab, polarParams->N, polarParams->N / 64, false); + simde__m256i zeros = simde_mm256_setzero_si256(); + // this code packs the one bit per byte of G_N into a packed bits G_N_tab for (int i = 0; i < polarParams->N; i++) { - polarParams->G_N_tab[i] = (uint64_t *)memalign(32, (polarParams->N / 64) * sizeof(uint64_t)); - memset((void *)polarParams->G_N_tab[i], 0, (polarParams->N / 64) * sizeof(uint64_t)); - - for (int j = 0; j < polarParams->N; j++) - polarParams->G_N_tab[i][j / 64] |= ((uint64_t)polarParams->G_N[i][j]) << (j & 63); - + for (int j = 0; j < polarParams->N; j += 64) { + const simde__m256i tmp1 = simde_mm256_cmpgt_epi8(*(simde__m256i *)&polarParams->G_N[i][j], zeros); + const simde__m256i tmp2 = simde_mm256_cmpgt_epi8(*(simde__m256i *)&polarParams->G_N[i][j + 32], zeros); + // cast directly to uint64_t from int32_t propagates the sign bit (in gcc) + const uint32_t part1 = simde_mm256_movemask_epi8(tmp1); + const uint32_t part2 = simde_mm256_movemask_epi8(tmp2); + pp[i][j / 64] = ((uint64_t)part2 << 32) | part1; + } #ifdef DEBUG_POLAR_ENCODER printf("Bit %d Selecting row %d of G : ", i, i); @@ -519,17 +519,13 @@ void polar_encoder_fast(uint64_t *A, //int bitlen0=bitlen; #ifdef POLAR_CODING_DEBUG - int A_array = (bitlen + 63) >> 6; printf("\nTX\n"); printf("a: "); - for (int n = 0; n < bitlen; n++) { - if (n % 4 == 0) { - printf(" "); - } - int n1 = n >> 6; - int n2 = n - (n1 << 6); - int alen = n1 == 0 ? bitlen - (A_array << 6) : 64; - printf("%lu", (A[A_array - 1 - n1] >> (alen - 1 - n2)) & 1); + for (int n = (bitlen + 63)/64 ; n >=0; n--) { + if (n % 4 == 0) + printf(" "); + if (n < bitlen) + printf("%lu", (A[n/64] >> (n%64)) & 1); } printf("\n"); #endif @@ -692,7 +688,7 @@ void polar_encoder_fast(uint64_t *A, #endif uint64_t D[8] = {0}; - nr_polar_uxG(D, u, (const uint64_t **)polarParams->G_N_tab, polarParams->N); + nr_polar_uxG(D, u, polarParams->G_N_tab, polarParams->N); #ifdef POLAR_CODING_DEBUG printf("d: "); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c index 1e065dd3a77061271c023aad7ad8f342f314401e..31eff0318580c134dd9cdb8600ac0b57f327cebf 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_procedures.c @@ -119,22 +119,19 @@ void nr_polar_info_extraction_from_u(uint64_t *Cprime, } } -void nr_polar_uxG(uint64_t *D, const uint64_t *u, const uint64_t **G_N_tab, uint16_t N) +void nr_polar_uxG(uint64_t *D, const uint64_t *u, const fourDimArray_t *G_N_tab, uint16_t N) { - int N_array = N >> 6; - + const int N64 = N / 64; + cast2Darray(g_n, uint64_t, G_N_tab); for (int n = 0; n < N; n++) { - const uint64_t *Gn = G_N_tab[N - 1 - n]; + const uint64_t *Gn = g_n[N - 1 - n]; int n_ones = 0; - for (int a = 0; a < N_array; a++) { - uint64_t uxG = u[a] & Gn[a]; - if (uxG != 0) - n_ones += count_bits_set(uxG); - } + for (int a = 0; a < N64; a++) + n_ones += count_bits_set(u[a] & Gn[a]); - int n1 = n >> 6; - int n2 = n - (n1 << 6); + int n1 = n / 64; + int n2 = n - (n1 * 64); D[n1] |= ((uint64_t)n_ones & 1) << n2; } } @@ -147,8 +144,7 @@ void nr_polar_bit_insertion(uint8_t *input, int16_t *Q_PC_N, uint8_t n_PC) { - uint16_t k=0; - uint8_t flag; + int k = 0; if (n_PC>0) { /* @@ -156,22 +152,16 @@ void nr_polar_bit_insertion(uint8_t *input, */ } else { for (int n=0; n<=N-1; n++) { - flag=0; + output[n] = 0; for (int m=0; m<=(K+n_PC)-1; m++) { if ( n == Q_I_N[m]) { - flag=1; - break; - } - } - if (flag) { // n ϵ Q_I_N - output[n]=input[k]; - k++; - } else { - output[n] = 0; + output[n] = input[k]; + k++; + break; + } } } } - } @@ -179,7 +169,7 @@ uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max) { - uint8_t n_1, n_2, n_min=5, n; + int n_1, n_2, n_min = 5; double R_min=1.0/8; if ( (E <= (9.0/8)*pow(2,ceil(log2(E))-1)) && (K/E < 9.0/16) ) { @@ -189,8 +179,8 @@ uint32_t nr_polar_output_length(uint16_t K, } n_2 = ceil(log2(K/R_min)); - - n=n_max; + + int n = n_max; if (n>n_1) n=n_1; if (n>n_2) n=n_2; if (n<n_min) n=n_min; @@ -201,19 +191,14 @@ uint32_t nr_polar_output_length(uint16_t K, return ((uint32_t) pow(2.0,n)); //=polar_code_output_length } - -void nr_polar_channel_interleaver_pattern(uint16_t *cip, - uint8_t I_BIL, - uint16_t E) +void nr_polar_channel_interleaver_pattern(uint16_t *cip, const uint8_t I_BIL, const uint16_t E) { if (I_BIL == 1) { - uint16_t T=0, k; + int T = E; while( ((T/2)*(T+1)) < E ) T++; - - int16_t **v = malloc(T * sizeof(*v)); - for (int i = 0; i <= T-1; i++) v[i] = malloc((T-i) * sizeof(*(v[i]))); - - k=0; + + int16_t v[T][T]; + int k = 0; for (int i = 0; i <= T-1; i++) { for (int j = 0; j <= (T-1)-i; j++) { if (k<E) { @@ -234,16 +219,11 @@ void nr_polar_channel_interleaver_pattern(uint16_t *cip, } } } - - for (int i = 0; i <= T-1; i++) free(v[i]); - free(v); - } else { for (int i=0; i<=E-1; i++) cip[i]=i; } } - void nr_polar_info_bit_pattern(uint8_t *ibp, uint8_t *pcbp, int16_t *Q_I_N, @@ -253,47 +233,46 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, const uint16_t *Q_0_Nminus1, uint16_t K, uint16_t N, - uint16_t E, + const uint16_t E, uint8_t n_PC, uint8_t n_pc_wm) { - int16_t *Q_Ftmp_N = malloc(sizeof(int16_t) * (N + 1)); // Last element shows the final - int16_t *Q_Itmp_N = malloc(sizeof(int16_t) * (N + 1)); // array index assigned a value. + int Q_Ftmp_N[N + 1]; // Last element shows the final + int Q_Itmp_N[N + 1]; // array index assigned a value. for (int i = 0; i <= N; i++) { Q_Ftmp_N[i] = -1; // Empty array. Q_Itmp_N[i] = -1; } - uint8_t flag; - uint16_t limit, ind; + int limit; if (E < N) { if ((K / (double)E) <= (7.0 / 16)) { // puncturing for (int n = 0; n <= N - E - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = J[n]; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + int ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = J[n]; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } if ((E / (double)N) >= (3.0 / 4)) { limit = ceil((double)(3 * N - 2 * E) / 4); for (int n = 0; n <= limit - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = n; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + int ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } } else { limit = ceil((double)(9 * N - 4 * E) / 16); for (int n = 0; n <= limit - 1; n++) { - ind = Q_Ftmp_N[N] + 1; - Q_Ftmp_N[ind] = n; - Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + int ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } } } else { // shortening for (int n = E; n <= N - 1; n++) { - ind = Q_Ftmp_N[N] + 1; + int ind = Q_Ftmp_N[N] + 1; Q_Ftmp_N[ind] = J[n]; Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; } @@ -302,13 +281,12 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, // Q_I,tmp_N = Q_0_N-1 \ Q_F,tmp_N for (int n = 0; n <= N - 1; n++) { - flag = 1; - for (int m = 0; m <= Q_Ftmp_N[N]; m++) { + bool flag = true; + for (int m = 0; m <= Q_Ftmp_N[N]; m++) if (Q_0_Nminus1[n] == Q_Ftmp_N[m]) { - flag = 0; + flag = false; break; } - } if (flag) { Q_Itmp_N[Q_Itmp_N[N] + 1] = Q_0_Nminus1[n]; Q_Itmp_N[N]++; @@ -317,7 +295,7 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, // Q_I_N comprises (K+n_PC) most reliable bit indices in Q_I,tmp_N for (int n = 0; n <= (K + n_PC) - 1; n++) { - ind = Q_Itmp_N[N] + n - ((K + n_PC) - 1); + int ind = Q_Itmp_N[N] + n - ((K + n_PC) - 1); Q_I_N[n] = Q_Itmp_N[ind]; } @@ -330,13 +308,12 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, // Q_F_N = Q_0_N-1 \ Q_I_N for (int n = 0; n <= N - 1; n++) { - flag = 1; - for (int m = 0; m <= (K + n_PC) - 1; m++) { + bool flag = true; + for (int m = 0; m <= (K + n_PC) - 1; m++) if (Q_0_Nminus1[n] == Q_I_N[m]) { - flag = 0; + flag = false; break; } - } if (flag) { Q_F_N[Q_F_N[N] + 1] = Q_0_Nminus1[n]; Q_F_N[N]++; @@ -361,11 +338,7 @@ void nr_polar_info_bit_pattern(uint8_t *ibp, break; } } - } - - free(Q_Ftmp_N); - free(Q_Itmp_N); } @@ -391,22 +364,21 @@ void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t N, uint16_t E) { - uint8_t i; - uint16_t *d, ind; - d = (uint16_t *)malloc(sizeof(uint16_t) * N); - uint16_t* y = calloc(N, sizeof(uint16_t)); - - for (int m=0; m<=N-1; m++) d[m]=m; + uint16_t d[N]; + for (int m = 0; m < N; m++) + d[m] = m; + uint16_t y[N]; + memset(y, 0, sizeof(y)); for (int m=0; m<=N-1; m++){ - i=floor((32*m)/N); + int i = floor((32 * m) / N); J[m] = (P_i_[i]*(N/32)) + (m%(N/32)); y[m] = d[J[m]]; } if (E>=N) { //repetition for (int k=0; k<=E-1; k++) { - ind = (k%N); + int ind = (k % N); rmp[k]=y[ind]; } } else { @@ -420,9 +392,6 @@ void nr_polar_rate_matching_pattern(uint16_t *rmp, } } } - - free(d); - free(y); } @@ -459,9 +428,9 @@ void nr_polar_rm_deinterleaving_cb(const int16_t *in, int16_t *out, const uint16 { int T = ceil((sqrt(8 * E + 1) - 1) / 2); int v_tab[T][T]; + memset(v_tab, 0, sizeof(v_tab)); int k = 0; for (int i = 0; i < T; i++) { - memset(v_tab[i], 0, T * sizeof(int)); for (int j = 0; j < T - i; j++) { if (k < E) { v_tab[i][j] = k + 1; @@ -484,7 +453,7 @@ void nr_polar_rm_deinterleaving_cb(const int16_t *in, int16_t *out, const uint16 } k = 0; - memset(out, 0, E * sizeof(int16_t)); + memset(out, 0, E * sizeof(*out)); for (int i = 0; i < T; i++) { for (int j = 0; j < T - i; j++) { if (v[i][j] != INT_MAX) { @@ -508,12 +477,12 @@ void nr_polar_rate_matching_int16(int16_t *input, } if (E >= N) { // repetition - memset((void *)output, 0, N * sizeof(int16_t)); + memset(output, 0, N * sizeof(*output)); for (int i = 0; i <= E - 1; i++) output[rmp[i]] += input[i]; } else { if ((K / (double)E) <= (7.0 / 16)) - memset((void *)output, 0, N * sizeof(int16_t)); // puncturing + memset(output, 0, N * sizeof(*output)); // puncturing else { // shortening for (int i = 0; i <= N - 1; i++) output[i] = 32767; // instead of INFINITY, to prevent [-Woverflow] diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c index d23760305936857190d03885ca9efe93b5796aec..013bdc73216bbbcd2008619824ff4128f34cae53 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c @@ -23,39 +23,34 @@ #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, const uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E){ - - uint8_t i; - uint16_t *d, *y, ind; - d = (uint16_t *)malloc(sizeof(uint16_t) * N); - y = (uint16_t *)malloc(sizeof(uint16_t) * N); - - for (int m=0; m<=N-1; m++) d[m]=m; - - for (int m=0; m<=N-1; m++){ - i=floor((32*m)/N); - J[m] = (P_i_[i]*(N/32)) + (m%(N/32)); - y[m] = d[J[m]]; - } - - if (E>=N) { //repetition - for (int k=0; k<=E-1; k++) { - ind = (k%N); - rmp[k]=y[ind]; - } - } else { - if ( (K/(double)E) <= (7.0/16) ) { //puncturing - for (int k=0; k<=E-1; k++) { - rmp[k]=y[k+N-E]; - } - } else { //shortening - for (int k=0; k<=E-1; k++) { - rmp[k]=y[k]; - } - } - } - - free(d); - free(y); + int d[N]; + int y[N]; + + for (int m = 0; m <= N - 1; m++) + d[m] = m; + + for (int m = 0; m <= N - 1; m++) { + i = floor((32 * m) / N); + J[m] = (P_i_[i] * (N / 32)) + (m % (N / 32)); + y[m] = d[J[m]]; + } + + if (E >= N) { // repetition + for (int k = 0; k <= E - 1; k++) { + ind = (k % N); + rmp[k] = y[ind]; + } + } else { + if ((K / (double)E) <= (7.0 / 16)) { // puncturing + for (int k = 0; k <= E - 1; k++) { + rmp[k] = y[k + N - E]; + } + } else { // shortening + for (int k = 0; k <= E - 1; k++) { + rmp[k] = y[k]; + } + } + } } diff --git a/openair1/PHY/CODING/nr_polar_init.c b/openair1/PHY/CODING/nr_polar_init.c index 23830cc010111faa9369eb768762215be796364f..3d6d7848da3548ae5752a55465f85cd5a587de21 100644 --- a/openair1/PHY/CODING/nr_polar_init.c +++ b/openair1/PHY/CODING/nr_polar_init.c @@ -48,10 +48,7 @@ static void nr_polar_delete_list(t_nrPolar_params * polarParams) { nr_polar_delete_list(polarParams->nextPtr); delete_decoder_tree(polarParams); - //From build_polar_tables() - for (int n=0; n < polarParams->N; n++) - if (polarParams->G_N_tab[n]) - free(polarParams->G_N_tab[n]); + // From build_polar_tables() free(polarParams->G_N_tab); free(polarParams->rm_tab); if (polarParams->crc_generator_matrix) diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 2b617fc5a0cb2dd0607eb17eb9679ae71ff2ab39..3d338fb114150f509c1993fee81d51777f1a209e 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -241,71 +241,74 @@ void nr_modulation(uint32_t *in, AssertFatal(false,"Invalid or unsupported modulation order %d\n",mod_order); } -void nr_layer_mapping(int16_t **mod_symbs, +void nr_layer_mapping(int nbCodes, + int encoded_len, + c16_t mod_symbs[nbCodes][encoded_len], uint8_t n_layers, + int layerSz, uint32_t n_symbs, - int16_t **tx_layers) + c16_t tx_layers[n_layers][layerSz]) { LOG_D(PHY,"Doing layer mapping for %d layers, %d symbols\n",n_layers,n_symbs); switch (n_layers) { case 1: - memcpy((void*)tx_layers[0], (void*)mod_symbs[0], (n_symbs<<1)*sizeof(int16_t)); - break; + memcpy(tx_layers[0], mod_symbs[0], n_symbs * sizeof(**mod_symbs)); + break; case 2: case 3: case 4: - for (int i=0; i<n_symbs/n_layers; i++) - for (int l=0; l<n_layers; l++) { - tx_layers[l][i<<1] = mod_symbs[0][(n_layers*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][((n_layers*i+l)<<1)+1]; - } + for (int i = 0; i < n_symbs / n_layers; i++) { + const c16_t *base = mod_symbs[0] + n_layers * i; + for (int l = 0; l < n_layers; l++) + tx_layers[l][i] = base[l]; + } break; case 5: - for (int i=0; i<n_symbs>>1; i++) - for (int l=0; l<2; l++) { - tx_layers[l][i<<1] = mod_symbs[0][((i<<1)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<1)+l)<<1)+1]; - } - for (int i=0; i<n_symbs/3; i++) - for (int l=2; l<5; l++) { - tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; - } + for (int i = 0; i < n_symbs; i += 2) { + const int txIdx = i / 2; + for (int l = 0; l < 2; l++) + tx_layers[l][txIdx] = mod_symbs[0][i + l]; + } + for (int i = 0; i < n_symbs; i += 3) { + const int txIdx = i / 3; + for (int l = 2; l < 5; l++) + tx_layers[l][txIdx] = mod_symbs[1][i + l]; + } break; case 6: for (int q=0; q<2; q++) - for (int i=0; i<n_symbs/3; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[q][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[q][((3*i+l)<<1)+1]; - } + for (int i = 0; i < n_symbs; i += 3) { + const int txIdx = i / 3; + for (int l = 0; l < 3; l++) + tx_layers[l][txIdx] = mod_symbs[q][i + l]; + } break; case 7: - for (int i=0; i<n_symbs/3; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1]; - } - for (int i=0; i<n_symbs/4; i++) - for (int l=3; l<7; l++) { - tx_layers[l][i<<1] = mod_symbs[0][((i<<2)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<2)+l)<<1)+1]; - } + for (int i = 0; i < n_symbs; i += 3) { + const int txIdx = i / 3; + for (int l = 0; l < 3; l++) + tx_layers[l][txIdx] = mod_symbs[1][i + l]; + } + for (int i = 0; i < n_symbs; i += 4) { + const int txIdx = i / 4; + for (int l = 3; l < 7; l++) + tx_layers[l][txIdx] = mod_symbs[0][i + l]; + } break; case 8: for (int q=0; q<2; q++) - for (int i=0; i<n_symbs>>2; i++) - for (int l=0; l<3; l++) { - tx_layers[l][i<<1] = mod_symbs[q][((i<<2)+l)<<1]; - tx_layers[l][(i<<1)+1] = mod_symbs[q][(((i<<2)+l)<<1)+1]; - } + for (int i = 0; i < n_symbs; i += 4) { + const int txIdx = i / 4; + for (int l = 0; l < 3; l++) + tx_layers[l][txIdx] = mod_symbs[q][i + l]; + } break; default: @@ -694,17 +697,17 @@ int nr_layer_precoder(int16_t **datatx_F_precoding, const char *prec_matrix, uin ((int16_t *)precodatatx_F)[1] = (int16_t)((((int16_t *)precodatatx_F)[1]*ONE_OVER_SQRT2_Q15)>>15);*/ } -int nr_layer_precoder_cm(int16_t **datatx_F_precoding, int *prec_matrix, uint8_t n_layers, int32_t re_offset) +c16_t nr_layer_precoder_cm(int n_layers, + int n_symbols, + int symSz, + c16_t datatx_F_precoding[n_layers][n_symbols][symSz], + c16_t *prec_matrix, + int symbol, + int offset) { - int32_t precodatatx_F = 0; - for (int al = 0; al<n_layers; al++) { - int16_t antenna_re = datatx_F_precoding[al][re_offset<<1]; - int16_t antenna_im = datatx_F_precoding[al][(re_offset<<1) +1]; - //printf("antenna precoding: %d %d\n",((int16_t *)&prec_matrix[al])[0],((int16_t *)&prec_matrix[al])[1]); - ((int16_t *) &precodatatx_F)[0] += (int16_t)(((int32_t)(antenna_re*(((int16_t *)&prec_matrix[al])[0])) - (int32_t)(antenna_im* (((int16_t *)&prec_matrix[al])[1])))>>15); - ((int16_t *) &precodatatx_F)[1] += (int16_t)(((int32_t)(antenna_re*(((int16_t *)&prec_matrix[al])[1])) + (int32_t)(antenna_im* (((int16_t *)&prec_matrix[al])[0])))>>15); - } - + c16_t precodatatx_F = {0}; + for (int al = 0; al < n_layers; al++) + precodatatx_F = c16maddShift(datatx_F_precoding[al][symbol][offset], prec_matrix[al], precodatatx_F, 15); return precodatatx_F; } diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h index be3cc33afc2f3aa04a56a60544246874b366da95..45cd4858e8eb44da7487a84229f71b409dd00a47 100644 --- a/openair1/PHY/MODULATION/nr_modulation.h +++ b/openair1/PHY/MODULATION/nr_modulation.h @@ -54,10 +54,13 @@ void nr_modulation(uint32_t *in, @param[out] tx_layers, modulated symbols for each layer */ -void nr_layer_mapping(int16_t **mod_symbs, - uint8_t n_layers, - uint32_t n_symbs, - int16_t **tx_layers); +void nr_layer_mapping(int nbCodes, + int encoded_len, + c16_t mod_symbs[nbCodes][encoded_len], + uint8_t n_layers, + int layerSz, + uint32_t n_symbs, + c16_t tx_layers[n_layers][layerSz]); /*! \brief Perform NR layer mapping. TS 38.211 V15.4.0 subclause 7.3.1.3 @param[in] ulsch_ue, double Pointer to NR_UE_ULSCH_t struct @@ -135,9 +138,11 @@ void apply_nr_rotation_RX(NR_DL_FRAME_PARMS *frame_parms, @param[in] n_layers, number of DLSCH layers */ int nr_layer_precoder(int16_t **datatx_F_precoding, const char *prec_matrix, uint8_t n_layers, int32_t re_offset); - -int nr_layer_precoder_cm(int16_t **datatx_F_precoding, - int *prec_matrix, - uint8_t n_layers, - int32_t re_offset); +c16_t nr_layer_precoder_cm(int n_layers, + int n_symbols, + int symSz, + c16_t datatx_F_precoding[n_layers][n_symbols][symSz], + c16_t *prec_matrix, + int symbol, + int offset); #endif diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 8d81b42fdf425ec9486351b64792efb7ebbbe4fc..b1f9f1a1aa764e8915abf1156753f1683f907c34 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -53,15 +53,10 @@ void nr_pdsch_codeword_scrambling(uint8_t *in, nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out); } -void nr_generate_pdsch(processingData_L1tx_t *msgTx, - int frame, - int slot) { - +void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) +{ PHY_VARS_gNB *gNB = msgTx->gNB; - NR_gNB_DLSCH_t *dlsch; - c16_t** txdataF = gNB->common_vars.txdataF; - int16_t amp = gNB->TX_AMP; - int xOverhead = 0; + const int16_t amp = gNB->TX_AMP; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats; time_stats_t *dlsch_scrambling_stats=&gNB->dlsch_scrambling_stats; @@ -75,25 +70,17 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats; for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) { - dlsch = &msgTx->dlsch[dlsch_id][0]; + NR_gNB_DLSCH_t *dlsch = msgTx->dlsch[dlsch_id]; NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; - int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; - int16_t **tx_layers = (int16_t**)dlsch->txdataF; - int8_t Wf[2], Wt[2], l0, l_prime, l_overline, delta; - uint8_t dmrs_Type = rel15->dmrsConfigType; - int nb_re_dmrs; - uint16_t n_dmrs; + const int layerSz = frame_parms->N_RB_DL * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * 8; + c16_t tx_layers[rel15->nrOfLayers][layerSz] __attribute__((aligned(64))); + const int dmrs_Type = rel15->dmrsConfigType; + const int nb_re_dmrs = rel15->numDmrsCdmGrpsNoData * (rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4); LOG_D(PHY,"pdsch: BWPStart %d, BWPSize %d, rbStart %d, rbsize %d\n", rel15->BWPStart,rel15->BWPSize,rel15->rbStart,rel15->rbSize); - if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { - nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; - } - else { - nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; - } - n_dmrs = (rel15->BWPStart+rel15->rbStart+rel15->rbSize)*nb_re_dmrs; + const int n_dmrs = (rel15->BWPStart + rel15->rbStart + rel15->rbSize) * nb_re_dmrs; if(rel15->dlDmrsScramblingId != gNB->pdsch_gold_init[rel15->SCID]) { gNB->pdsch_gold_init[rel15->SCID] = rel15->dlDmrsScramblingId; @@ -101,16 +88,16 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, } uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot]; - uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100 - uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos); - uint32_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers; - uint8_t Qm = rel15->qamModOrder[0]; - uint32_t encoded_length = nb_re*Qm; - int16_t mod_dmrs[n_dmrs<<1] __attribute__ ((aligned(16))); + const int dmrs_symbol_map = rel15->dlDmrsSymbPos; // single DMRS: 010000100 Double DMRS 110001100 + const int xOverhead = 0; + const int nb_re = + (12 * rel15->NrOfSymbols - nb_re_dmrs * get_num_dmrs(rel15->dlDmrsSymbPos) - xOverhead) * rel15->rbSize * rel15->nrOfLayers; + const int Qm = rel15->qamModOrder[0]; + const int encoded_length = nb_re * Qm; /* PTRS */ uint16_t dlPtrsSymPos = 0; - uint16_t n_ptrs = 0; + int n_ptrs = 0; uint32_t ptrsSymbPerSlot = 0; if(rel15->pduBitmap & 0x1) { set_ptrs_symb_idx(&dlPtrsSymPos, @@ -125,7 +112,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, /// CRC, coding, interleaving and rate matching AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); - unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(32))); + unsigned char output[rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers] __attribute__((aligned(64))); bzero(output,rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers); start_meas(dlsch_encoding_stats); @@ -163,18 +150,14 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, if (IS_SOFTMODEM_DLSIM) memcpy(harq->f, output, encoded_length); - for (int q=0; q<rel15->NrOfCodewords; q++) { + c16_t mod_symbs[rel15->NrOfCodewords][encoded_length]; + for (int codeWord = 0; codeWord < rel15->NrOfCodewords; codeWord++) { /// scrambling start_meas(dlsch_scrambling_stats); uint32_t scrambled_output[(encoded_length>>5)+4]; // modulator acces by 4 bytes in some cases memset(scrambled_output, 0, sizeof(scrambled_output)); if ( encoded_length > rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers) abort(); - nr_pdsch_codeword_scrambling(output, - encoded_length, - q, - rel15->dataScramblingId, - rel15->rnti, - scrambled_output); + nr_pdsch_codeword_scrambling(output, encoded_length, codeWord, rel15->dataScramblingId, rel15->rnti, scrambled_output); #ifdef DEBUG_DLSCH printf("PDSCH scrambling:\n"); @@ -188,36 +171,30 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, stop_meas(dlsch_scrambling_stats); /// Modulation start_meas(dlsch_modulation_stats); - nr_modulation(scrambled_output, - encoded_length, - Qm, - mod_symbs[q]); + nr_modulation(scrambled_output, encoded_length, Qm, (int16_t *)mod_symbs[codeWord]); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_MODULATION, 0); stop_meas(dlsch_modulation_stats); #ifdef DEBUG_DLSCH printf("PDSCH Modulation: Qm %d(%u)\n", Qm, nb_re); - for (int i=0; i<nb_re>>3; i++) { + for (int i = 0; i < nb_re; i += 8) { for (int j=0; j<8; j++) { - printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]); + printf("%d %d\t", mod_symbs[codeWord][i + j].r, mod_symbs[codeWord][i + j].i); } printf("\n"); } #endif } - + start_meas(&gNB->dlsch_layer_mapping_stats); /// Layer mapping - nr_layer_mapping(mod_symbs, - rel15->nrOfLayers, - nb_re, - tx_layers); + nr_layer_mapping(rel15->NrOfCodewords, encoded_length, mod_symbs, rel15->nrOfLayers, layerSz, nb_re, tx_layers); #ifdef DEBUG_DLSCH printf("Layer mapping (%d layers):\n", rel15->nrOfLayers); for (int l=0; l<rel15->nrOfLayers; l++) - for (int i=0; i<(nb_re/rel15->nrOfLayers)>>3; i++) { - printf("layer %d, Re %d..%d : ",l,i<<3,(i<<3)+7); + for (int i = 0; i < nb_re / rel15->nrOfLayers; i += 8) { + printf("layer %d, Re %d..%d : ", l, i, i + 7); for (int j=0; j<8; j++) { - printf("l%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]); + printf("l%d %d\t", tx_layers[l][i + j].r, tx_layers[l][i + j].i); } printf("\n"); } @@ -232,10 +209,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, if (start_sc >= frame_parms->ofdm_symbol_size) start_sc -= frame_parms->ofdm_symbol_size; - int txdataF_offset = slot*frame_parms->samples_per_slot_wCP; - int16_t **txdataF_precoding = (int16_t **)malloc16(rel15->nrOfLayers*sizeof(int16_t *)); - for (int layer = 0; layer<rel15->nrOfLayers; layer++) - txdataF_precoding[layer] = (int16_t *)malloc16(2*14*frame_parms->ofdm_symbol_size*sizeof(int16_t)); + const uint32_t txdataF_offset = slot*frame_parms->samples_per_slot_wCP; + c16_t txdataF_precoding[rel15->nrOfLayers][NR_NUMBER_OF_SYMBOLS_PER_SLOT][frame_parms->ofdm_symbol_size] __attribute__((aligned(64)));; #ifdef DEBUG_DLSCH_MAPPING printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_re %u,nb_layers %d)\n", @@ -243,63 +218,66 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, #endif start_meas(&gNB->dlsch_resource_mapping_stats); - for (int nl=0; nl<rel15->nrOfLayers; nl++) { - - int dmrs_port = get_dmrs_port(nl,rel15->dmrsPorts); + for (int layer = 0; layer < rel15->nrOfLayers; layer++) { + int dmrs_port = get_dmrs_port(layer, rel15->dmrsPorts); // DMRS params for this dmrs port + int Wt[2], Wf[2]; get_Wt(Wt, dmrs_port, dmrs_Type); get_Wf(Wf, dmrs_port, dmrs_Type); - delta = get_delta(dmrs_port, dmrs_Type); - l_prime = 0; // single symbol nl 0 - l0 = get_l0(rel15->dlDmrsSymbPos); - l_overline = l0; + const int8_t delta = get_delta(dmrs_port, dmrs_Type); + int8_t l_prime = 0; // single symbol layer 0 + int8_t l_overline = get_l0(rel15->dlDmrsSymbPos); #ifdef DEBUG_DLSCH_MAPPING - uint8_t dmrs_symbol = l0+l_prime; - printf("DMRS Type %d params for nl %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", - 1+dmrs_Type,nl, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime, l0, dmrs_symbol); + uint8_t dmrs_symbol = l_overline + l_prime; + printf("DMRS Type %d params for layer %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n", + 1 + dmrs_Type, + layer, + Wt[0], + Wt[1], + Wf[0], + Wf[1], + delta, + l_prime, + l_overline, + dmrs_symbol); #endif uint32_t m=0, dmrs_idx=0; + AssertFatal(n_dmrs, "n_dmrs can't be 0\n"); + c16_t mod_dmrs[n_dmrs] __attribute__((aligned(64))); // Loop Over OFDM symbols: - for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) { + for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) { /// DMRS QPSK modulation uint8_t k_prime=0; uint16_t n=0; - - if ((dmrs_symbol_map & (1 << l))){ // DMRS time occasion + if ((dmrs_symbol_map & (1 << l_symbol))) { // DMRS time occasion // The reference point for is subcarrier 0 of the lowest-numbered resource block in CORESET 0 if the corresponding // PDCCH is associated with CORESET 0 and Type0-PDCCH common search space and is addressed to SI-RNTI // 3GPP TS 38.211 V15.8.0 Section 7.4.1.1.2 Mapping to physical resources - if (rel15->rnti==SI_RNTI) { - if (dmrs_Type==NFAPI_NR_DMRS_TYPE1) { - dmrs_idx = rel15->rbStart*6; - } else { - dmrs_idx = rel15->rbStart*4; - } - } else { - if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) { - dmrs_idx = (rel15->rbStart+rel15->BWPStart)*6; - } else { - dmrs_idx = (rel15->rbStart+rel15->BWPStart)*4; - } - } - if (l==(l_overline+1)) //take into account the double DMRS symbols + dmrs_idx = rel15->rbStart; + if (rel15->rnti != SI_RNTI) + dmrs_idx += rel15->BWPStart; + dmrs_idx *= dmrs_Type == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; + if (l_symbol == (l_overline + 1)) // take into account the double DMRS symbols l_prime = 1; - else if (l>(l_overline+1)) {//new DMRS pair - l_overline = l; + else if (l_symbol > (l_overline + 1)) { // new DMRS pair + l_overline = l_symbol; l_prime = 0; } /// DMRS QPSK modulation - nr_modulation(pdsch_dmrs[l][rel15->SCID], n_dmrs*2, DMRS_MOD_ORDER, mod_dmrs); // Qm = 2 as DMRS is QPSK modulated + nr_modulation(pdsch_dmrs[l_symbol][rel15->SCID], + n_dmrs * DMRS_MOD_ORDER, + DMRS_MOD_ORDER, + (int16_t *)mod_dmrs); // Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DLSCH - printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs, dmrs_Type); - for (int i=0; i<n_dmrs>>4; i++) { + printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l_symbol, n_dmrs, dmrs_Type); + for (int i = 0; i < n_dmrs / 2; i += 8) { for (int j=0; j<8; j++) { - printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]); + printf("%d %d\t", mod_dmrs[i + j].r, mod_dmrs[i + j].i); } printf("\n"); } @@ -307,22 +285,19 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, } /* calculate if current symbol is PTRS symbols */ - uint16_t ptrs_idx = 0; - int16_t *mod_ptrs = NULL; - uint8_t ptrs_symbol = 0; + int ptrs_idx = 0; + int ptrs_symbol = 0; + c16_t mod_ptrs[max(n_ptrs, 1)] __attribute__((aligned(64))); //max only to please sanitizer, that kills if 0 even if it is not a error if(rel15->pduBitmap & 0x1) { - ptrs_symbol = is_ptrs_symbol(l, dlPtrsSymPos); + ptrs_symbol = is_ptrs_symbol(l_symbol, dlPtrsSymPos); if(ptrs_symbol) { /* PTRS QPSK Modulation for each OFDM symbol in a slot */ - LOG_D(PHY,"Doing ptrs modulation for symbol %d, n_ptrs %d\n", l, n_ptrs); - int16_t mod_ptrsBuf[n_ptrs<<1] __attribute__ ((aligned(16))); - mod_ptrs = mod_ptrsBuf; - nr_modulation(pdsch_dmrs[l][rel15->SCID], (n_ptrs << 1), DMRS_MOD_ORDER, mod_ptrs); + LOG_D(PHY, "Doing ptrs modulation for symbol %d, n_ptrs %d\n", l_symbol, n_ptrs); + nr_modulation(pdsch_dmrs[l_symbol][rel15->SCID], n_ptrs * DMRS_MOD_ORDER, DMRS_MOD_ORDER, (int16_t *)mod_ptrs); } } uint16_t k = start_sc; - if (ptrs_symbol || dmrs_symbol_map & (1 << l)) { - + if (ptrs_symbol || dmrs_symbol_map & (1 << l_symbol)) { // Loop Over SCs: for (int i=0; i<rel15->rbSize*NR_NB_SC_PER_RB; i++) { /* check if cuurent RE is PTRS RE*/ @@ -338,14 +313,18 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, frame_parms->ofdm_symbol_size); } /* Map DMRS Symbol */ - if ( (dmrs_symbol_map & (1 << l)) && - (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) { - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 ] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15; + if ((dmrs_symbol_map & (1 << l_symbol)) + && (k == ((start_sc + get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type)) % (frame_parms->ofdm_symbol_size)))) { + txdataF_precoding[layer][l_symbol][k] = c16mulRealShift(mod_dmrs[dmrs_idx], Wt[l_prime] * Wf[k_prime] * amp, 15); #ifdef DEBUG_DLSCH_MAPPING printf("dmrs_idx %u\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n", - dmrs_idx, l, k, k_prime, n, txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1)], - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]); + dmrs_idx, + l_symbol, + k, + k_prime, + n, + txdataF_precoding[layer][l_symbol][k].r, + txdataF_precoding[layer][l_symbol][k].i); #endif dmrs_idx++; k_prime++; @@ -353,38 +332,49 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, n+=(k_prime)?0:1; } /* Map PTRS Symbol */ - else if(is_ptrs_re){ + else if (is_ptrs_re) { uint16_t beta_ptrs = 1; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15; + txdataF_precoding[layer][l_symbol][k] = c16mulRealShift(mod_ptrs[ptrs_idx], beta_ptrs * amp, 15); #ifdef DEBUG_DLSCH_MAPPING printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d, mod_ptrs: %d %d\n", - ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF_precoding[nl])[((l*frame_parms->ofdm_symbol_size + k)<<1)], - ((int16_t*)txdataF_precoding[nl])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1],mod_ptrs[ptrs_idx<<1],mod_ptrs[(ptrs_idx<<1)+1]); + ptrs_idx, + l_symbol, + k, + k_prime, + n, + txdataF_precoding[layer][l_symbol][k].r, + txdataF_precoding[layer][l_symbol][k].i, + mod_ptrs[ptrs_idx].r, + mod_ptrs[ptrs_idx].i); #endif ptrs_idx++; } - /* Map DATA Symbol */ - else if( ptrs_symbol || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = (amp * tx_layers[nl][m<<1]) >> 15; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[nl][(m<<1) + 1]) >> 15; + /* Map DATA Symbol */ + else if (ptrs_symbol + || allowed_xlsch_re_in_dmrs_symbol(k, + start_sc, + frame_parms->ofdm_symbol_size, + rel15->numDmrsCdmGrpsNoData, + dmrs_Type)) { + txdataF_precoding[layer][l_symbol][k] = c16mulRealShift(tx_layers[layer][m], amp, 15); #ifdef DEBUG_DLSCH_MAPPING printf("m %u\t l %d \t k %d \t txdataF: %d %d\n", - m, l, k, txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1)], - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]); + m, + l_symbol, + k, + txdataF_precoding[layer][l_symbol][k].r, + txdataF_precoding[layer][l_symbol][k].i); #endif m++; } /* mute RE */ else { - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = 0; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = 0; + txdataF_precoding[layer][l_symbol][k] = (c16_t){0}; } if (++k >= frame_parms->ofdm_symbol_size) k -= frame_parms->ofdm_symbol_size; } //RE loop - } - else { // no PTRS or DMRS in this symbol + } else { // no PTRS or DMRS in this symbol // Loop Over SCs: int upper_limit=rel15->rbSize*NR_NB_SC_PER_RB; int remaining_re = 0; @@ -393,27 +383,28 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, upper_limit = frame_parms->ofdm_symbol_size - start_sc; } // fix the alignment issues later, use 64-bit SIMD below instead of 128. + // can be made with loadu/storeu if (0/*(frame_parms->N_RB_DL&1)==0*/) { - simde__m128i *txF=(simde__m128i*)&txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size+start_sc)<<1)]; + simde__m128i *txF = (simde__m128i *)&txdataF_precoding[layer][l_symbol][start_sc]; - simde__m128i *txl = (simde__m128i*)&tx_layers[nl][m<<1]; + simde__m128i *txl = (simde__m128i *)&tx_layers[layer][m]; simde__m128i amp128=simde_mm_set1_epi16(amp); for (int i=0; i<(upper_limit>>2); i++) { txF[i] = simde_mm_mulhrs_epi16(amp128,txl[i]); } //RE loop, first part m+=upper_limit; if (remaining_re > 0) { - txF = (simde__m128i*)&txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size)<<1)]; - txl = (simde__m128i*)&tx_layers[nl][m<<1]; - for (int i=0; i<(remaining_re>>2); i++) { - txF[i] = simde_mm_mulhrs_epi16(amp128,txl[i]); - } + txF = (simde__m128i *)&txdataF_precoding[layer][l_symbol]; + txl = (simde__m128i *)&tx_layers[layer][m]; + for (int i = 0; i < (remaining_re >> 2); i++) { + txF[i] = simde_mm_mulhrs_epi16(amp128, txl[i]); + } } } else { - simde__m128i *txF = (simde__m128i *)&txdataF_precoding[nl][((l * frame_parms->ofdm_symbol_size + start_sc) << 1)]; + simde__m128i *txF = (simde__m128i *)&txdataF_precoding[layer][l_symbol][start_sc]; - simde__m128i *txl = (simde__m128i *)&tx_layers[nl][m << 1]; + simde__m128i *txl = (simde__m128i *)&tx_layers[layer][m]; simde__m128i amp64 = simde_mm_set1_epi16(amp); int i; for (i = 0; i < (upper_limit >> 2); i++) { @@ -421,19 +412,22 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, simde_mm_storeu_si128(txF + i, simde_mm_mulhrs_epi16(amp64, txL)); #ifdef DEBUG_DLSCH_MAPPING if ((i&1) > 0) - printf("m %u\t l %d \t k %d \t txdataF: %d %d\n", - m, l, start_sc+(i>>1), txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1)], - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + start_sc+(i>>1))<<1) + 1]); + printf("m %u\t l %d \t k %d \t txdataF: %d %d\n", + m, + l_symbol, + start_sc + (i >> 1), + txdataF_precoding[layer][l_symbol][start_sc].r, + txdataF_precoding[layer][l_symbol][start_sc].i); #endif /* handle this, mute RE */ /*else { - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = 0; - txdataF_precoding[anl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = 0; + txdataF_precoding[layer][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = 0; + txdataF_precoding[layer][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = 0; }*/ } if (i * 4 != upper_limit) { - c16_t *txFc = (c16_t *)&txdataF_precoding[nl][((l * frame_parms->ofdm_symbol_size + start_sc) << 1)]; - c16_t *txlc = (c16_t *)&tx_layers[nl][m << 1]; + c16_t *txFc = &txdataF_precoding[layer][l_symbol][start_sc]; + c16_t *txlc = &tx_layers[layer][m]; for (i = (upper_limit >> 2) << 2; i < upper_limit; i++) { txFc[i].r = ((txlc[i].r * amp) >> 14) + 1; txFc[i].i = ((txlc[i].i * amp) >> 14) + 1; @@ -441,8 +435,8 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, } m+=upper_limit; if (remaining_re > 0) { - txF = (simde__m128i *)&txdataF_precoding[nl][((l * frame_parms->ofdm_symbol_size) << 1)]; - txl = (simde__m128i *)&tx_layers[nl][m << 1]; + txF = (simde__m128i *)&txdataF_precoding[layer][l_symbol]; + txl = (simde__m128i *)&tx_layers[layer][m]; int i; for (i = 0; i < (remaining_re >> 2); i++) { const simde__m128i txL = simde_mm_loadu_si128(txl + i); @@ -451,29 +445,32 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, #ifdef DEBUG_DLSCH_MAPPING if ((i&1) > 0) printf("m %u\t l %d \t k %d \t txdataF: %d %d\n", - m, l, i>>1, txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) ], - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + (i>>1))<<1) + 1]); + m, + l_symbol, + i >> 1, + txdataF_precoding[layer][l_symbol][i >> 1].r, + txdataF_precoding[layer][l_symbol][i >> 1].i); #endif /* handle this, mute RE */ - /*else { - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = 0; - txdataF_precoding[nl][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = 0; - }*/ + /*else { + txdataF_precoding[layer][((l*frame_parms->ofdm_symbol_size + k)<<1) ] = 0; + txdataF_precoding[layer][((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = 0; + }*/ } // RE loop, second part if (i * 4 != remaining_re) { - c16_t *txFc = (c16_t *)&txdataF_precoding[nl][((l * frame_parms->ofdm_symbol_size) << 1)]; - c16_t *txlc = (c16_t *)&tx_layers[nl][m << 1]; + c16_t *txFc = txdataF_precoding[layer][l_symbol]; + c16_t *txlc = &tx_layers[layer][m]; for (i = (remaining_re >> 2) << 2; i < remaining_re; i++) { txFc[i].r = ((txlc[i].r * amp) >> 14) + 1; txFc[i].i = ((txlc[i].i * amp) >> 14) + 1; } } - } // + } // remaining_re > 0 m+=remaining_re; } // N_RB_DL even - } // no DMRS/PTRS in symbol + } // no DMRS/PTRS in symbol } // symbol loop - }// layer loop + } // layer loop stop_meas(&gNB->dlsch_resource_mapping_stats); ///Layer Precoding and Antenna port mapping @@ -484,13 +481,15 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, // The Precoding matrix: // The Codebook Type I start_meas(&gNB->dlsch_precoding_stats); + c16_t **txdataF = gNB->common_vars.txdataF; - for (int ap=0; ap<frame_parms->nb_antennas_tx; ap++) { - - for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) { - uint16_t k = start_sc; + for (int ant = 0; ant < frame_parms->nb_antennas_tx; ant++) { + for (int l_symbol = rel15->StartSymbolIndex; l_symbol < rel15->StartSymbolIndex + rel15->NrOfSymbols; l_symbol++) { + uint16_t subCarrier = start_sc; for (int rb=0; rb<rel15->rbSize; rb++) { + const size_t txdataF_offset_per_symbol = l_symbol * frame_parms->ofdm_symbol_size + txdataF_offset; + //get pmi info uint8_t pmi; if (0 /*rel15->precodingAndBeamforming.prg_size > 0*/) @@ -499,76 +498,79 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, pmi = 0;//no precoding if (pmi == 0) {//unitary Precoding - if (k + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC - if(ap<rel15->nrOfLayers) - memcpy((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], - (void*)&txdataF_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)], - NR_NB_SC_PER_RB*sizeof(int32_t)); + if (subCarrier + NR_NB_SC_PER_RB <= frame_parms->ofdm_symbol_size) { // RB does not cross DC + if (ant < rel15->nrOfLayers) + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][l_symbol][subCarrier], + NR_NB_SC_PER_RB * sizeof(**txdataF)); else - memset((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], - 0, - NR_NB_SC_PER_RB*sizeof(int32_t)); + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + 0, + NR_NB_SC_PER_RB * sizeof(**txdataF)); } else { // RB does cross DC - int neg_length = frame_parms->ofdm_symbol_size - k; + int neg_length = frame_parms->ofdm_symbol_size - subCarrier; int pos_length = NR_NB_SC_PER_RB - neg_length; - if (ap<rel15->nrOfLayers) { - memcpy((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], - (void*)&txdataF_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)], - neg_length*sizeof(int32_t)); - memcpy((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset], - (void*)&txdataF_precoding[ap][2*(l*frame_parms->ofdm_symbol_size)], - pos_length*sizeof(int32_t)); + if (ant < rel15->nrOfLayers) { + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][l_symbol][subCarrier], + neg_length * sizeof(**txdataF)); + memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant][l_symbol], pos_length * sizeof(**txdataF)); } else { - memset((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], - 0, - neg_length*sizeof(int32_t)); - memset((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset], - 0, - pos_length*sizeof(int32_t)); + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + 0, + neg_length * sizeof(**txdataF)); + memset(&txdataF[ant][txdataF_offset_per_symbol], + 0, + pos_length * sizeof(**txdataF)); } } - k += NR_NB_SC_PER_RB; - if (k >= frame_parms->ofdm_symbol_size) { - k -= frame_parms->ofdm_symbol_size; + subCarrier += NR_NB_SC_PER_RB; + if (subCarrier >= frame_parms->ofdm_symbol_size) { + subCarrier -= frame_parms->ofdm_symbol_size; } } else { if(frame_parms->nb_antennas_tx==1){//no precoding matrix defined - memcpy((void*)&txdataF[ap][l*frame_parms->ofdm_symbol_size + txdataF_offset + k], - (void*)&txdataF_precoding[ap][2*(l*frame_parms->ofdm_symbol_size + k)], - NR_NB_SC_PER_RB*sizeof(int32_t)); - k += NR_NB_SC_PER_RB; - if (k >= frame_parms->ofdm_symbol_size) { - k -= frame_parms->ofdm_symbol_size; + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[ant][l_symbol][subCarrier], + NR_NB_SC_PER_RB * sizeof(**txdataF)); + subCarrier += NR_NB_SC_PER_RB; + if (subCarrier >= frame_parms->ofdm_symbol_size) { + subCarrier -= frame_parms->ofdm_symbol_size; } } else { //get the precoding matrix weights: - int32_t **mat = gNB->nr_mimo_precoding_matrix[rel15->nrOfLayers-1]; + c16_t **mat = (c16_t**)gNB->nr_mimo_precoding_matrix[rel15->nrOfLayers - 1]; //i_row =0,...,dl_antenna_port //j_col =0,...,nrOfLayers //mat[pmi][i_rows*2+j_col] - int *W_prec; - W_prec = (int32_t *)&mat[pmi][ap*rel15->nrOfLayers]; + c16_t *W_prec = &mat[pmi][ant * rel15->nrOfLayers]; for (int i=0; i<NR_NB_SC_PER_RB; i++) { - int32_t re_offset = l*frame_parms->ofdm_symbol_size + k; - int32_t precodatatx_F = nr_layer_precoder_cm(txdataF_precoding, W_prec, rel15->nrOfLayers, re_offset); - ((int16_t*)txdataF[ap])[(re_offset<<1) + (2*txdataF_offset)] = ((int16_t *) &precodatatx_F)[0]; - ((int16_t*)txdataF[ap])[(re_offset<<1) + 1 + (2*txdataF_offset)] = ((int16_t *) &precodatatx_F)[1]; - #ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t k %d \t txdataF: %d %d\n", - ap, l, k, ((int16_t*)txdataF[ap])[(re_offset<<1) + (2*txdataF_offset)], - ((int16_t*)txdataF[ap])[(re_offset<<1) + 1 + (2*txdataF_offset)]); - #endif - if (++k >= frame_parms->ofdm_symbol_size) { - k -= frame_parms->ofdm_symbol_size; + txdataF[ant][txdataF_offset_per_symbol + subCarrier] = nr_layer_precoder_cm(rel15->nrOfLayers, + NR_SYMBOLS_PER_SLOT, + frame_parms->ofdm_symbol_size, + txdataF_precoding, + W_prec, + l_symbol, + subCarrier); +#ifdef DEBUG_DLSCH_MAPPING + printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", + ant, + l_symbol, + subCarrier, + txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].r, + txdataF[ant][l_symbol * frame_parms->ofdm_symbol_size + subCarrier + txdataF_offset].i); +#endif + if (++subCarrier >= frame_parms->ofdm_symbol_size) { + subCarrier -= frame_parms->ofdm_symbol_size; } } } } } //RB loop } // symbol loop - }// port loop + } // port loop stop_meas(&gNB->dlsch_precoding_stats); @@ -587,9 +589,6 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, else { LOG_D(PHY,"beam index for PDSCH allocation already taken\n"); } - for (int layer = 0; layer<rel15->nrOfLayers; layer++) - free16(txdataF_precoding[layer],2*14*frame_parms->ofdm_symbol_size); - free16(txdataF_precoding,rel15->nrOfLayers); }// dlsch loop } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 0b240ac488c775642e48ef462b3ff05b2c87025e..04a320be248a42fbd4258d042729188708a75e0c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -74,18 +74,11 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch, uint16_t N_RB, const NR_DL_FRAME_PARM free(harq->c); free(harq->pdu); - int nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1; - for (int q=0; q<nb_codewords; q++) - free(dlsch->mod_symbs[q]); - free(dlsch->mod_symbs); - for (int layer = 0; layer < max_layers; layer++) { - free(dlsch->txdataF[layer]); for (int aa = 0; aa < 64; aa++) free(dlsch->ue_spec_bf_weights[layer][aa]); free(dlsch->ue_spec_bf_weights[layer]); } - free(dlsch->txdataF); free(dlsch->ue_spec_bf_weights); } @@ -103,10 +96,6 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment NR_gNB_DLSCH_t dlsch; - int txdataf_size = frame_parms->N_RB_DL*NR_SYMBOLS_PER_SLOT*NR_NB_SC_PER_RB*8; // max pdsch encoded length for each layer - - dlsch.txdataF = (int32_t **)malloc16(max_layers * sizeof(int32_t *)); - dlsch.ue_spec_bf_weights = (int32_t ***)malloc16(max_layers * sizeof(int32_t **)); for (int layer=0; layer<max_layers; layer++) { dlsch.ue_spec_bf_weights[layer] = (int32_t **)malloc16(64 * sizeof(int32_t *)); @@ -118,14 +107,8 @@ NR_gNB_DLSCH_t new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms, uint16_t N_RB) dlsch.ue_spec_bf_weights[layer][aa][re] = 0x00007fff; } } - dlsch.txdataF[layer] = (int32_t *)malloc16((txdataf_size) * sizeof(int32_t)); } - int nb_codewords = NR_MAX_NB_LAYERS > 4 ? 2 : 1; - dlsch.mod_symbs = (int32_t **)malloc16(nb_codewords * sizeof(int32_t *)); - for (int q=0; q<nb_codewords; q++) - dlsch.mod_symbs[q] = (int32_t *)malloc16(txdataf_size * max_layers * sizeof(int32_t)); - NR_DL_gNB_HARQ_t *harq = &dlsch.harq_process; bzero(harq, sizeof(NR_DL_gNB_HARQ_t)); harq->b = malloc16(dlsch_bytes); diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c index 85d3cf3be17ef17bc55cdebd29056a2419acbc64..a88c429d44e7307555f7bc6b5311cc22e1e57fe5 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c @@ -65,14 +65,16 @@ void get_antenna_ports(uint8_t *ap, uint8_t n_symbs, uint8_t config) { *(ap+i) = i; } -void get_Wt(int8_t *Wt, uint8_t ap, uint8_t config) { +void get_Wt(int *Wt, const int ap, const nfapi_nr_dmrs_type_e config) +{ for (int i=0; i<2; i++) - *(Wt+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][5+i]):(pdsch_dmrs_2[ap][5+i]); + Wt[i] = (config == NFAPI_NR_DMRS_TYPE1) ? (pdsch_dmrs_1[ap][5 + i]) : (pdsch_dmrs_2[ap][5 + i]); } -void get_Wf(int8_t *Wf, uint8_t ap, uint8_t config) { +void get_Wf(int *Wf, const int ap, const nfapi_nr_dmrs_type_e config) +{ for (int i=0; i<2; i++) - *(Wf+i)=(config==NFAPI_NR_DMRS_TYPE1)?(pdsch_dmrs_1[ap][3+i]):(pdsch_dmrs_2[ap][3+i]); + Wf[i] = (config == NFAPI_NR_DMRS_TYPE1) ? (pdsch_dmrs_1[ap][3 + i]) : (pdsch_dmrs_2[ap][3 + i]); } uint8_t get_delta(uint8_t ap, uint8_t config) { diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h index 491e24658e46b747edfbeac88a73068a3036c932..0754611eed188b287a1dc518fe6ddc4609463c7f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h @@ -39,10 +39,8 @@ #define NR_PDSCH_DMRS_NB_ANTENNA_PORTS 12 void get_antenna_ports(uint8_t *ap, uint8_t n_symbs, uint8_t config); - -void get_Wt(int8_t *Wt, uint8_t ap, uint8_t config); - -void get_Wf(int8_t *Wf, uint8_t ap, uint8_t config); +void get_Wt(int *Wt, const int ap, const nfapi_nr_dmrs_type_e config); +void get_Wf(int *Wf, const int ap, const nfapi_nr_dmrs_type_e config); uint8_t get_delta(uint8_t ap, uint8_t config); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index e0b0313462e4a5a1e62f2c5e488db64279f266d3..9c59535e16a66e0630f39360154d264abeffa1ba 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -116,7 +116,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE, { LOG_D(PHY,"nr_ue_ulsch_procedures hard_id %d %d.%d\n",harq_pid,frame,slot); - int8_t Wf[2], Wt[2]; + int Wf[2], Wt[2]; int l_prime[2], delta; uint8_t nb_dmrs_re_per_rb; int i; diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 31ce89b5e452512f4b20563be82df04d4d644e27..61497871f8eb04fd028625d96de2b928b79e3159 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -193,6 +193,10 @@ extern "C" { }; } + __attribute__((always_inline)) inline c16_t c16mulRealShift(const c16_t a, const int32_t b, const int Shift) + { + return (c16_t){.r = (int16_t)((a.r * b) >> Shift), .i = (int16_t)((a.i * b) >> Shift)}; + } __attribute__((always_inline)) inline c16_t c16divShift(const c16_t a, const c16_t b, const int Shift) { return (c16_t) { .r = (int16_t)((a.r * b.r + a.i * b.i) >> Shift), diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 1e62e51c2a73da383188195c897af81f166ac5dd..20985cb08aa25608fab6b1f373c24069e03e33b7 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -142,10 +142,6 @@ typedef struct { typedef struct { /// Pointers to variables related to DLSCH harq process NR_DL_gNB_HARQ_t harq_process; - /// TX buffers for UE-spec transmission (antenna layers 1,...,4 after to precoding) - int32_t **txdataF; - /// Modulated symbols buffer - int32_t **mod_symbs; /// beamforming weights for UE-spec transmission (antenna ports 5 or 7..14), for each codeword, maximum 4 layers? int32_t ***ue_spec_bf_weights; /// Active flag for baseband transmitter processing diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index 0848714c2c99cc6c0ef230f295c7adc4b5320305..c4724b545834eee3d7a9cd2563dfad3467c7f937 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -464,6 +464,13 @@ typedef ul_info_transfer_cnf_t dl_info_transfer_cnf_t; */ typedef ul_info_transfer_ind_t dl_info_transfer_ind_t; +typedef struct nas_pdu_session_req_s { + int pdusession_id; + int pdusession_type; + int sst; + int sd; +} nas_pdu_session_req_t; + /* * -------------------------------------------------------------------------- * Radio Access Bearer establishment diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index dba73dd8b98908aafc14697e6a1e5e63ec8435e4..212c4009881d4bc34f0f4e4e8f1bfa173025cbf3 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -119,17 +119,39 @@ typedef struct drb_to_setup_s { cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; } drb_to_setup_t; -typedef struct qos_flow_to_setup_s { - long id; - fiveQI_type_t fiveQI_type; - long fiveQI; - long qoSPriorityLevel; - long packetDelayBudget; - long packetError_scalar; - long packetError_exponent; - long priorityLevel; - long pre_emptionCapability; - long pre_emptionVulnerability; +typedef struct qos_characteristics_s { + union { + struct { + long fiveqi; + long qos_priority_level; + } non_dynamic; + struct { + long fiveqi; // -1 -> optional + long qos_priority_level; + long packet_delay_budget; + struct { + long per_scalar; + long per_exponent; + } packet_error_rate; + } dynamic; + }; + fiveQI_type_t qos_type; +} qos_characteristics_t; + +typedef struct ngran_allocation_retention_priority_s { + uint16_t priority_level; + long preemption_capability; + long preemption_vulnerability; +} ngran_allocation_retention_priority_t; + +typedef struct qos_flow_level_qos_parameters_s { + qos_characteristics_t qos_characteristics; + ngran_allocation_retention_priority_t alloc_reten_priority; // additional members should be added!! +} qos_flow_level_qos_parameters_t; + +typedef struct qos_flow_setup_e { + long qfi; // qos flow identifier + qos_flow_level_qos_parameters_t qos_params; } qos_flow_to_setup_t; typedef struct DRB_nGRAN_to_setup_s { @@ -199,7 +221,7 @@ typedef struct e1ap_bearer_release_cplt_s { } e1ap_bearer_release_cplt_t; typedef struct qos_flow_setup_s { - long id; + long qfi; } qos_flow_setup_t; typedef struct DRB_nGRAN_setup_s { diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index d7d46f3bef91fa012b48797cf65b1169243968f4..c0d5c1b437c8696fb473f5590c4590188acc9a1c 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -284,12 +284,64 @@ typedef struct f1ap_up_tnl_s { uint16_t port; } f1ap_up_tnl_t; +typedef enum preemption_capability_e { + SHALL_NOT_TRIGGER_PREEMPTION, + MAY_TRIGGER_PREEMPTION, +} preemption_capability_t; + +typedef enum preemption_vulnerability_e { + NOT_PREEMPTABLE, + PREEMPTABLE, +} preemption_vulnerability_t; + +typedef struct f1ap_qos_characteristics_s { + union { + struct { + long fiveqi; + long qos_priority_level; + } non_dynamic; + struct { + long fiveqi; // -1 -> optional + long qos_priority_level; + long packet_delay_budget; + struct { + long per_scalar; + long per_exponent; + } packet_error_rate; + } dynamic; + }; + fiveQI_type_t qos_type; +} f1ap_qos_characteristics_t; + +typedef struct f1ap_ngran_allocation_retention_priority_s { + uint16_t priority_level; + preemption_capability_t preemption_capability; + preemption_vulnerability_t preemption_vulnerability; +} f1ap_ngran_allocation_retention_priority_t; + +typedef struct f1ap_qos_flow_level_qos_parameters_s { + f1ap_qos_characteristics_t qos_characteristics; + f1ap_ngran_allocation_retention_priority_t alloc_reten_priority; +} f1ap_qos_flow_level_qos_parameters_t; + +typedef struct f1ap_flows_mapped_to_drb_s { + long qfi; // qos flow identifier + f1ap_qos_flow_level_qos_parameters_t qos_params; +} f1ap_flows_mapped_to_drb_t; + +typedef struct f1ap_drb_information_s { + f1ap_qos_flow_level_qos_parameters_t drb_qos; + f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb; + uint8_t flows_to_be_setup_length; +} f1ap_drb_information_t; + typedef struct f1ap_drb_to_be_setup_s { long drb_id; f1ap_up_tnl_t up_ul_tnl[2]; uint8_t up_ul_tnl_length; f1ap_up_tnl_t up_dl_tnl[2]; uint8_t up_dl_tnl_length; + f1ap_drb_information_t drb_info; rlc_mode_t rlc_mode; nssai_t nssai; } f1ap_drb_to_be_setup_t; diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 25889468f2c4b38ffe18fe7111889bdf2ff24007..66b8719cc86e1b5624052fc441e690cc87c9992b 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -150,14 +150,14 @@ typedef enum ngap_priority_level_s { } ngap_priority_level_t; typedef enum ngap_pre_emp_capability_e { - NGAP_PRE_EMPTION_CAPABILITY_ENABLED = 0, - NGAP_PRE_EMPTION_CAPABILITY_DISABLED = 1, + NGAP_PRE_EMPTION_CAPABILITY_SHALL_NOT_TRIGGER_PREEMPTION = 0, + NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION = 1, NGAP_PRE_EMPTION_CAPABILITY_MAX, } ngap_pre_emp_capability_t; typedef enum ngap_pre_emp_vulnerability_e { - NGAP_PRE_EMPTION_VULNERABILITY_ENABLED = 0, - NGAP_PRE_EMPTION_VULNERABILITY_DISABLED = 1, + NGAP_PRE_EMPTION_VULNERABILITY_NOT_PREEMPTABLE = 0, + NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE = 1, NGAP_PRE_EMPTION_VULNERABILITY_MAX, } ngap_pre_emp_vulnerability_t; @@ -202,6 +202,7 @@ typedef struct nssai_s { typedef struct pdusession_level_qos_parameter_s { uint8_t qfi; uint64_t fiveQI; + uint64_t qos_priority; fiveQI_type_t fiveQI_type; ngap_allocation_retention_priority_t allocation_retention_priority; } pdusession_level_qos_parameter_t; diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index e4881f8d8a5f385c4c57492294a73b75d902d266..e1e9fce355ee890a61a82d027d4328d8eb177cf6 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -82,3 +82,4 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr // eNB: RLC -> RRC messages MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) +MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 037dfbe86cd3675a27f909f61ada6bf0b17afb2b..2810dcfdd65fca1c907e94a512ff9aa70f304b46 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -92,6 +92,7 @@ #define NRDuDlReq(mSGpTR) (mSGpTR)->ittiMsg.nr_du_dl_req #define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa +#define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req //-------------------------------------------------------------------------------------------// typedef struct RrcStateInd_s { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index 2aeb873c7140e6b86aa4349cbd582a7e59dfa4fb..353b8931e19c4443bdb3c0b4c43f8ef3a7c07f5d 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -655,24 +655,28 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear for (qos_flow_to_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlow2Setup; k++) { asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); - ieC6_1_1_1->qoS_Flow_Identifier = k->id; + ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; - if (k->fiveQI_type == non_dynamic) { // non Dynamic 5QI + qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; + if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); - non_Dynamic_5QI->fiveQI = k->fiveQI; + non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; } else { // dynamic 5QI ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); - dynamic_5QI->qoSPriorityLevel = k->qoSPriorityLevel; - dynamic_5QI->packetDelayBudget = k->packetDelayBudget; - dynamic_5QI->packetErrorRate.pER_Scalar = k->packetError_scalar; - dynamic_5QI->packetErrorRate.pER_Exponent = k->packetError_exponent; + dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level; + dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget; + dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar; + dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent; } - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = k->priorityLevel; - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = k->pre_emptionCapability; - ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = k->pre_emptionVulnerability; + ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = + rent_priority_in->preemption_capability; + ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = + rent_priority_in->preemption_vulnerability; } } } @@ -775,7 +779,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *r for (const qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); - ieC3_1_1_1->qoS_Flow_Identifier = k->id; + ieC3_1_1_1->qoS_Flow_Identifier = k->qfi; } } @@ -953,27 +957,32 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; drb->numQosFlow2Setup = qos2SetupList->list.count; for (int k=0; k < qos2SetupList->list.count; k++) { - qos_flow_to_setup_t *qos = drb->qosFlows + k; + qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; - qos->id = qos2Setup->qoS_Flow_Identifier; + qos_flow->qfi = qos2Setup->qoS_Flow_Identifier; + qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - qos->fiveQI_type = non_dynamic; - qos->fiveQI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; + qos_char->qos_type = non_dynamic; + qos_char->non_dynamic.fiveqi = + qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; } else { E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; - qos->fiveQI_type = dynamic; - qos->qoSPriorityLevel = dynamic5QI->qoSPriorityLevel; - qos->packetDelayBudget = dynamic5QI->packetDelayBudget; - qos->packetError_scalar = dynamic5QI->packetErrorRate.pER_Scalar; - qos->packetError_exponent = dynamic5QI->packetErrorRate.pER_Exponent; + qos_char->qos_type = dynamic; + qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; + qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; + qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; + qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent; } - qos->priorityLevel = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; - qos->pre_emptionCapability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; - qos->pre_emptionVulnerability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; + ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; + rent_priority->priority_level = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; + rent_priority->preemption_capability = + qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; + rent_priority->preemption_vulnerability = + qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; } } } @@ -1076,6 +1085,14 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, AssertFatal(false, "gTPTunnel information in required\n"); } } + + // Qos Flow Information + drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count; + for (int q = 0; q < drb->flow_Setup_List.list.count; q++) { + qos_flow_setup_t *qosflowSetup = &drbSetup->qosFlows[q]; + E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q]; + qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier; + } } } break; diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 6e6cd8558d61b658a8dd3f7c20f1f53036247989..3f4ff32f475d7246eae3c833f7b83b6e335ab089 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -152,7 +152,7 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3 } FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); + AssertFatal(dlBands == 1, "cannot handled more than one frequency band\n"); for (int dlB=0; dlB < dlBands; dlB++) { F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 94cecd6254e7725896934a1dee2b385d780339d0..08090a13955058435837be85006cf03879099b58 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -41,27 +41,28 @@ #include <openair3/ocp-gtpu/gtp_itf.h> #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" -static void setQos(F1AP_NonDynamic5QIDescriptor_t *toFill) { - asn1cCalloc(toFill, tmp); +static void setQos(F1AP_NonDynamic5QIDescriptor_t **toFill) +{ + asn1cCalloc(*toFill, tmp); /* fiveQI */ tmp->fiveQI = 1L; /* OPTIONAL */ /* qoSPriorityLevel */ if (0) { - asn1cCallocOne(toFill->qoSPriorityLevel, 1L); + asn1cCallocOne((*toFill)->qoSPriorityLevel, 1L); } /* OPTIONAL */ /* averagingWindow */ if (0) { - asn1cCallocOne(toFill->averagingWindow, 1L); + asn1cCallocOne((*toFill)->averagingWindow, 1L); } /* OPTIONAL */ /* maxDataBurstVolume */ if (0) { - asn1cCallocOne(toFill->maxDataBurstVolume, 1L); + asn1cCallocOne((*toFill)->maxDataBurstVolume, 1L); } } @@ -271,8 +272,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu asn1cSequenceAdd(out->protocolIEs.list, F1AP_UEContextSetupRequestIEs_t, ie12); ie12->id = F1AP_ProtocolIE_ID_id_DRBs_ToBeSetup_List; ie12->criticality = F1AP_Criticality_reject; - ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; - LOG_I(F1AP, "Length of drbs_to_be_setup: %d \n", f1ap_ue_context_setup_req->drbs_to_be_setup_length); + ie12->value.present = F1AP_UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; for (int i = 0; i < f1ap_ue_context_setup_req->drbs_to_be_setup_length; i++) { // @@ -329,7 +329,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu if (some_decide_qoS_characteristics) { DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - setQos(DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI); + setQos(&DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI); } else { DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI, tmp); @@ -429,7 +429,7 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu if (some_decide_qoS_characteristics) { QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - setQos(QosParams->choice.non_Dynamic_5QI); + setQos(&QosParams->choice.non_Dynamic_5QI); } else { QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI; asn1cCalloc(QosParams->choice.dynamic_5QI, tmp); @@ -1227,6 +1227,7 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte else{ /* 12.1.2 DRB_Information */ + f1ap_drb_information_t *drb_info_in = &f1ap_ue_context_modification_req->drbs_to_be_setup->drb_info; drbs_toBeSetupMod_item->qoSInformation.present = F1AP_QoSInformation_PR_choice_extension; F1AP_QoSInformation_ExtIEs_t *ie = (F1AP_QoSInformation_ExtIEs_t *)calloc(1, sizeof(*ie)); ie->id = F1AP_ProtocolIE_ID_id_DRB_Information; @@ -1237,48 +1238,56 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte /* 12.1.2.1 dRB_QoS */ { /* qoS_Characteristics */ + f1ap_qos_flow_level_qos_parameters_t *drb_qos_in = &drb_info_in->drb_qos; { - int some_decide_qoS_characteristics = 0; // BK: Need Check + int some_decide_qoS_characteristics = drb_qos_in->qos_characteristics.qos_type; - if (some_decide_qoS_characteristics) { + f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; + if (some_decide_qoS_characteristics == non_dynamic) { DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - setQos(DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI); + asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.non_Dynamic_5QI, tmp); + + /* 5QI */ + tmp->fiveQI = drb_qos_char_in->non_dynamic.fiveqi; } else { - DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; - asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI, tmp); - /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = 1L; - /* packetDelayBudget */ - tmp->packetDelayBudget = 1L; - /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = 1L; - tmp->packetErrorRate.pER_Exponent = 6L; + DRB_Information->dRB_QoS.qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_dynamic_5QI; + asn1cCalloc(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI, tmp); + /* qoSPriorityLevel */ + tmp->qoSPriorityLevel = drb_qos_char_in->dynamic.qos_priority_level; + /* packetDelayBudget */ + tmp->packetDelayBudget = drb_qos_char_in->dynamic.packet_delay_budget; + /* packetErrorRate */ + tmp->packetErrorRate.pER_Scalar = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; + tmp->packetErrorRate.pER_Exponent = drb_qos_char_in->dynamic.packet_error_rate.per_scalar; - /* OPTIONAL */ - /* delayCritical */ - if (0) { - asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L); - } + /* OPTIONAL */ + /* delayCritical */ + if (0) { + asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->delayCritical, 1L); + } - /* OPTIONAL */ - /* averagingWindow */ - if (0) { - asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L); - } + /* OPTIONAL */ + /* averagingWindow */ + if (0) { + asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->averagingWindow, 1L); + } - /* OPTIONAL */ - /* maxDataBurstVolume */ - if (0) { - asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L); - } - } // if some_decide_qoS_characteristics + /* OPTIONAL */ + /* maxDataBurstVolume */ + if (0) { + asn1cCallocOne(DRB_Information->dRB_QoS.qoS_Characteristics.choice.dynamic_5QI->maxDataBurstVolume, 1L); + } + } // if some_decide_qoS_characteristics } // qoS_Characteristics /* nGRANallocationRetentionPriority */ { - DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum - DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.priorityLevel = + drb_qos_in->alloc_reten_priority.priority_level; + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionCapability = + drb_qos_in->alloc_reten_priority.preemption_capability; + DRB_Information->dRB_QoS.nGRANallocationRetentionPriority.pre_emptionVulnerability = + drb_qos_in->alloc_reten_priority.preemption_vulnerability; } // nGRANallocationRetentionPriority /* OPTIONAL */ @@ -1327,33 +1336,40 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte F1AP_NotificationControl_active); // enum } - /* 12.1.2.4 flows_Mapped_To_DRB_List */ // BK: need verifiy - - for (int k = 0; k < 1; k ++) { + /* 12.1.2.4 flows_Mapped_To_DRB_List */ + for (int k = 0; k < drb_info_in->flows_to_be_setup_length; k++) { asn1cSequenceAdd(DRB_Information->flows_Mapped_To_DRB_List.list, F1AP_Flows_Mapped_To_DRB_Item_t, flows_mapped_to_drb_item); + + f1ap_flows_mapped_to_drb_t *qos_flow_in = drb_info_in->flows_mapped_to_drb + k; + /* qoSFlowIndicator */ - flows_mapped_to_drb_item->qoSFlowIdentifier = 1L; + flows_mapped_to_drb_item->qoSFlowIdentifier = qos_flow_in->qfi; /* qoSFlowLevelQoSParameters */ { + f1ap_qos_flow_level_qos_parameters_t *flow_qos_params_in = &qos_flow_in->qos_params; /* qoS_Characteristics */ { - int some_decide_qoS_characteristics = 0; // BK: Need Check - F1AP_QoS_Characteristics_t *QosParams=&flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.qoS_Characteristics; + int some_decide_qoS_characteristics = flow_qos_params_in->qos_characteristics.qos_type; + F1AP_QoS_Characteristics_t *QosParams = &flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.qoS_Characteristics; + f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics; - if (some_decide_qoS_characteristics) { + if (some_decide_qoS_characteristics == non_dynamic) { QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; - setQos(QosParams->choice.non_Dynamic_5QI); + asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); + + /* 5QI */ + tmp->fiveQI = flow_qos_char_in->non_dynamic.fiveqi; } else { QosParams->present = F1AP_QoS_Characteristics_PR_dynamic_5QI; asn1cCalloc(QosParams->choice.dynamic_5QI, tmp); /* qoSPriorityLevel */ - tmp->qoSPriorityLevel = 1L; + tmp->qoSPriorityLevel = flow_qos_char_in->dynamic.qos_priority_level; /* packetDelayBudget */ - tmp->packetDelayBudget = 1L; + tmp->packetDelayBudget = flow_qos_char_in->dynamic.packet_delay_budget; /* packetErrorRate */ - tmp->packetErrorRate.pER_Scalar = 1L; - tmp->packetErrorRate.pER_Exponent = 6L; + tmp->packetErrorRate.pER_Scalar = flow_qos_char_in->dynamic.packet_error_rate.per_scalar; + tmp->packetErrorRate.pER_Exponent = flow_qos_char_in->dynamic.packet_error_rate.per_exponent; /* OPTIONAL */ /* delayCritical */ @@ -1380,9 +1396,12 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte } // qoS_Characteristics /* nGRANallocationRetentionPriority */ { - flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = F1AP_PriorityLevel_highest; // enum - flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = F1AP_Pre_emptionCapability_shall_not_trigger_pre_emption; // enum - flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = F1AP_Pre_emptionVulnerability_not_pre_emptable; // enum + flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = + flow_qos_params_in->alloc_reten_priority.priority_level; + flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = + flow_qos_params_in->alloc_reten_priority.preemption_capability; + flows_mapped_to_drb_item->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = + flow_qos_params_in->alloc_reten_priority.preemption_vulnerability; } // nGRANallocationRetentionPriority /* OPTIONAL */ diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index fe7b8c78f5669c368d6f356cb6f8c6e47e16f36e..4eee1ba6b155b3ed64c328f696232121168d2f60 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -893,11 +893,99 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension; if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { - F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; + F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information; + f1ap_drb_information_t *drb_info = &f1ap_ue_context_modification_req->drbs_to_be_setup->drb_info; + + /* 12.1.2.1 dRB_QoS */ + { + /* QoS-Flow-Level-QoS-Parameters */ + f1ap_qos_flow_level_qos_parameters_t *drb_qos = &drb_info->drb_qos; + F1AP_QoSFlowLevelQoSParameters_t *dRB_QoS = &dRB_Info->dRB_QoS; + { + /* QoS Characteristics*/ + f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics; + F1AP_QoS_Characteristics_t *dRB_QoS_Char = &dRB_QoS->qoS_Characteristics; + + if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + drb_qos_char->qos_type = non_dynamic; + drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI; + drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) + ? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel + : -1; + } else { + drb_qos_char->qos_type = dynamic; + drb_qos_char->dynamic.fiveqi = + (dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1; + drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; + drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget; + drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; + drb_qos_char->dynamic.packet_error_rate.per_exponent = + dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; + } + } + + /* nGRANallocationRetentionPriority */ + drb_qos->alloc_reten_priority.priority_level = dRB_QoS->nGRANallocationRetentionPriority.priorityLevel; + drb_qos->alloc_reten_priority.preemption_vulnerability = + dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; + drb_qos->alloc_reten_priority.preemption_capability = + dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; + } // dRB_QoS + + // 12.1.2.4 flows_Mapped_To_DRB_List + drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count; + drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t)); + AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n"); + + for (int k = 0; k < drb_p->drb_info.flows_to_be_setup_length; k++) { + f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = drb_info->flows_mapped_to_drb + k; + F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = dRB_Info->flows_Mapped_To_DRB_List.list.array[0] + k; + + flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier; + + /* QoS-Flow-Level-QoS-Parameters */ + { + f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params; + F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters; + + /* QoS Characteristics*/ + { + f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics; + F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics; + + if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { + flow_qos_char->qos_type = non_dynamic; + flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI; + flow_qos_char->non_dynamic.qos_priority_level = + (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) + ? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel + : -1; + } else { + flow_qos_char->qos_type = dynamic; + flow_qos_char->dynamic.fiveqi = + (Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1; + flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; + flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget; + flow_qos_char->dynamic.packet_error_rate.per_scalar = + Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar; + flow_qos_char->dynamic.packet_error_rate.per_exponent = + Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent; + } + } + + /* nGRANallocationRetentionPriority */ + flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel; + flow_qos->alloc_reten_priority.preemption_vulnerability = + Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; + flow_qos->alloc_reten_priority.preemption_capability = + Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability; + } + } + /* S-NSSAI */ - OCTET_STRING_TO_INT8(&DRB_Information->sNSSAI.sST, drb_p->nssai.sst); - if (DRB_Information->sNSSAI.sD != NULL) - memcpy((uint8_t *)&drb_p->nssai.sd, DRB_Information->sNSSAI.sD->buf, 3); + OCTET_STRING_TO_INT8(&dRB_Info->sNSSAI.sST, drb_p->nssai.sst); + if (dRB_Info->sNSSAI.sD != NULL) + memcpy((uint8_t *)&drb_p->nssai.sd, dRB_Info->sNSSAI.sD->buf, 3); else drb_p->nssai.sd = 0xffffff; } diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 537349ac345e238f6dbf4f96d1e7f9ca159c95a6..9ffd98062783856aa23166eecfc820c5db5b9a80 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -942,6 +942,59 @@ void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac, *p_UE_FR1 : *p_NR_FR1); } +void configure_maccellgroup(NR_UE_MAC_INST_t *mac, const NR_MAC_CellGroupConfig_t *mcg) +{ + NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info; + if (mcg->drx_Config) + LOG_E(NR_MAC, "DRX not implemented! Configuration not handled!\n"); + if (mcg->schedulingRequestConfig) { + const NR_SchedulingRequestConfig_t *src = mcg->schedulingRequestConfig; + if (src->schedulingRequestToReleaseList) { + for (int i = 0; i < src->schedulingRequestToReleaseList->list.count; i++) { + if (*src->schedulingRequestToReleaseList->list.array[i] == si->sr_id) { + si->SR_COUNTER = 0; + si->sr_ProhibitTimer = 0; + si->sr_ProhibitTimer_Running = 0; + si->sr_id = -1; // invalid init value + } + else + LOG_E(NR_MAC, "Cannot release SchedulingRequestConfig. Not configured.\n"); + } + } + if (src->schedulingRequestToAddModList) { + for (int i = 0; i < src->schedulingRequestToAddModList->list.count; i++) { + NR_SchedulingRequestToAddMod_t *sr = src->schedulingRequestToAddModList->list.array[i]; + AssertFatal(si->sr_id == -1 || + si->sr_id == sr->schedulingRequestId, + "Current implementation cannot handle more than 1 SR configuration\n"); + si->sr_id = sr->schedulingRequestId; + si->sr_TransMax = sr->sr_TransMax; + if (sr->sr_ProhibitTimer) + LOG_E(NR_MAC, "SR prohibit timer not properly implemented\n"); + } + } + } + if (mcg->bsr_Config) { + si->periodicBSR_Timer = mcg->bsr_Config->periodicBSR_Timer; + si->retxBSR_Timer = mcg->bsr_Config->retxBSR_Timer; + if (mcg->bsr_Config->logicalChannelSR_DelayTimer) + LOG_E(NR_MAC, "Handling of logicalChannelSR_DelayTimer not implemented\n"); + } + if (mcg->tag_Config) { + // TODO TAG not handled + if(mcg->tag_Config->tag_ToAddModList) { + for (int i = 0; i < mcg->tag_Config->tag_ToAddModList->list.count; i++) { + if (mcg->tag_Config->tag_ToAddModList->list.array[i]->timeAlignmentTimer != + NR_TimeAlignmentTimer_infinity) + LOG_E(NR_MAC, "TimeAlignmentTimer not handled\n"); + } + } + } + if (mcg->phr_Config) { + // TODO configuration when PHR is implemented + } +} + void nr_rrc_mac_config_req_cg(module_id_t module_id, int cc_idP, NR_CellGroupConfig_t *cell_group_config) @@ -950,9 +1003,8 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, AssertFatal(cell_group_config, "CellGroupConfig should not be NULL\n"); NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); - if (cell_group_config->mac_CellGroupConfig) { - // TODO handle MAC-CellGroupConfig - } + if (cell_group_config->mac_CellGroupConfig) + configure_maccellgroup(mac, cell_group_config->mac_CellGroupConfig); if (cell_group_config->physicalCellGroupConfig) configure_physicalcellgroup(mac, cell_group_config->physicalCellGroupConfig); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index c7bbee07802fbb945f9eb6efdf6c5d8c4a2942e9..0e57098d7b9ec0527b61c1d4dc96e5c6ff258248 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -196,8 +196,6 @@ typedef struct { NR_LC_SCHEDULING_INFO lc_sched_info[NR_MAX_NUM_LCID]; // lcg scheduling info NR_LCG_SCHEDULING_INFO lcg_sched_info[NR_MAX_NUM_LCGID]; - /// sum of all lcid buffer size - uint16_t All_lcid_buffer_size_lastTTI; /// SR pending as defined in 38.321 uint8_t SR_pending; /// SR_COUNTER as defined in 38.321 @@ -214,14 +212,9 @@ typedef struct { uint16_t sr_ProhibitTimer; /// sr ProhibitTime running uint8_t sr_ProhibitTimer_Running; - /// default value to n5 - uint16_t maxHARQ_Tx; - /// default value is false - uint16_t ttiBundling; - /// default value is release - struct DRX_Config *drx_config; - /// default value is release - struct MAC_MainConfig__phr_Config *phr_config; + // Maximum number of SR transmissions + uint32_t sr_TransMax; + int sr_id; ///timer before triggering a periodic PHR uint16_t periodicPHR_Timer; ///timer before triggering a prohibit PHR @@ -234,7 +227,6 @@ typedef struct { int16_t prohibitPHR_SF; ///DL Pathloss Change in db uint16_t PathlossChange_db; - /// default value is false uint16_t extendedBSR_Sizes_r10; /// default value is false diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2bb1691eae415ca413c5dd906de61f77439c3a72..310aceaf6f3a7844189f8abab3ff063d1c07efef 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -182,6 +182,7 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac) mac->scheduling_info.SR_COUNTER = 0; mac->scheduling_info.sr_ProhibitTimer = 0; mac->scheduling_info.sr_ProhibitTimer_Running = 0; + mac->scheduling_info.sr_id = -1; // invalid init value // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value // configured by the NW. @@ -2424,32 +2425,34 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p return sr_count > 0 ? true : false; } -int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot){ +int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot) +{ // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti DevCheck(module_idP < NB_NR_UE_MAC_INST, module_idP, NB_NR_UE_MAC_INST, 0); NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP); - DSR_TRANSMAX_t dsr_TransMax = sr_n64; // todo - LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n", + NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info; + int max_sr_transmissions = (1 << (2 + si->sr_TransMax)); + LOG_D(NR_MAC, "[UE %d] Frame %d slot %d send SR indication (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d\n", module_idP, frameP, slot, - mac->scheduling_info.SR_COUNTER, - (1 << (2 + dsr_TransMax)), - mac->scheduling_info.SR_pending); // todo + si->SR_COUNTER, + max_sr_transmissions, + si->SR_pending); // todo - if ((mac->scheduling_info.SR_pending == 1) && - (mac->scheduling_info.SR_COUNTER < (1 << (2 + dsr_TransMax)))) { - LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n", + if ((si->SR_pending == 1) && + (si->SR_COUNTER < max_sr_transmissions)) { + LOG_D(NR_MAC, "[UE %d] Frame %d slot %d PHY asks for SR (SR_COUNTER/sr_TransMax %d/%d), SR_pending %d, increment SR_COUNTER\n", module_idP, frameP, slot, - mac->scheduling_info.SR_COUNTER, - (1 << (2 + dsr_TransMax)), - mac->scheduling_info.SR_pending); // todo - mac->scheduling_info.SR_COUNTER++; + si->SR_COUNTER, + max_sr_transmissions, + si->SR_pending); // todo + si->SR_COUNTER++; // start the sr-prohibittimer : rel 9 and above - if (mac->scheduling_info.sr_ProhibitTimer > 0) { // timer configured - mac->scheduling_info.sr_ProhibitTimer--; - mac->scheduling_info.sr_ProhibitTimer_Running = 1; + if (si->sr_ProhibitTimer > 0) { // timer configured + si->sr_ProhibitTimer--; + si->sr_ProhibitTimer_Running = 1; } else { - mac->scheduling_info.sr_ProhibitTimer_Running = 0; + si->sr_ProhibitTimer_Running = 0; } //mac->ul_active =1; return (1); //instruct phy to signal SR @@ -2457,7 +2460,7 @@ int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot){ // notify RRC to relase PUCCH/SRS // clear any configured dl/ul // initiate RA - if (mac->scheduling_info.SR_pending) { + if (si->SR_pending) { // release all pucch resource //mac->physicalConfigDedicated = NULL; // todo //mac->ul_active = 0; // todo @@ -2465,9 +2468,8 @@ int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slot){ NR_BSR_TRIGGER_NONE; LOG_I(NR_MAC, "[UE %d] Release all SRs \n", module_idP); } - - mac->scheduling_info.SR_pending = 0; - mac->scheduling_info.SR_COUNTER = 0; + si->SR_pending = 0; + si->SR_COUNTER = 0; return (0); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 5157ff453f9d9db301ab48efc8e615fb6c18a2e8..c1313a495e47b272fa0870bd96055b3190827ec6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -30,6 +30,11 @@ #include "uper_decoder.h" #include "uper_encoder.h" +// Standarized 5QI values and Default Priority levels as mentioned in 3GPP TS 23.501 Table 5.7.4-1 +const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5, 6, 7, 8, 9, 69, 70, 79, 80, 82, 83, 84, 85, 86}; +const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10, + 60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18}; + static long get_lcid_from_drbid(int drb_id) { return drb_id + 3; /* LCID is DRB + 3 */ @@ -243,6 +248,49 @@ static void set_nssaiConfig(const int drb_len, const f1ap_drb_to_be_setup_t *req } } +static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ctrl_t *sched_ctrl) +{ + AssertFatal(req != NULL, "f1ap_ue_context_modif_req is NULL\n"); + uint8_t drb_count = req->drbs_to_be_setup_length; + uint8_t srb_count = req->srbs_to_be_setup_length; + LOG_I(NR_MAC, "Number of DRBs = %d and SRBs = %d\n", drb_count, srb_count); + + /* DRBs*/ + for (int i = 0; i < drb_count; i++) { + f1ap_drb_to_be_setup_t *drb_p = &req->drbs_to_be_setup[i]; + uint8_t nb_qos_flows = drb_p->drb_info.flows_to_be_setup_length; + long drb_id = drb_p->drb_id; + LOG_I(NR_MAC, "In %s: number of QOS flows mapped to DRB_id %d: %ld \n", __func__, drb_count, drb_id); + + for (int q = 0; q < nb_qos_flows; q++) { + f1ap_flows_mapped_to_drb_t *qos_flow = &drb_p->drb_info.flows_mapped_to_drb[q]; + + f1ap_qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; + uint64_t priority = qos_char->non_dynamic.qos_priority_level; + int64_t fiveqi = qos_char->non_dynamic.fiveqi; + if (qos_char->qos_type == dynamic) { + priority = qos_char->dynamic.qos_priority_level; + fiveqi = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; + } + if (qos_char->qos_type == non_dynamic) { + LOG_D(NR_MAC, "Qos Priority level is considered from the standarsdized 5QI to QoS mapping table\n"); + for (int id = 0; id < 26; id++) { + if (qos_fiveqi[id] == fiveqi) + priority = qos_priority[id]; + } + } + sched_ctrl->qos_config[drb_id - 1][q].fiveQI = fiveqi; + sched_ctrl->qos_config[drb_id - 1][q].priority = priority; + LOG_D(NR_MAC, + "In %s: drb_id %ld: 5QI %lu priority %lu\n", + __func__, + drb_id, + sched_ctrl->qos_config[drb_id - 1][q].fiveQI, + sched_ctrl->qos_config[drb_id - 1][q].priority); + } + } +} + void ue_context_setup_request(const f1ap_ue_context_setup_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; @@ -309,6 +357,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) /* TODO: need to apply after UE context reconfiguration confirmed? */ nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); + /* Fill the QoS config in MAC for each active DRB */ + set_QoSConfig(req, &UE->UE_sched_ctrl); + /* Set NSSAI config in MAC for each active DRB */ set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); @@ -409,6 +460,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); + /* Fill the QoS config in MAC for each active DRB */ + set_QoSConfig(req, &UE->UE_sched_ctrl); + /* Set NSSAI config in MAC for each active DRB */ set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); } else { @@ -553,8 +607,9 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) AssertFatal(*dl_rrc->old_gNB_DU_ue_id != dl_rrc->gNB_DU_ue_id, "logic bug: current and old gNB DU UE ID cannot be the same\n"); /* 38.401 says: "Find UE context based on old gNB-DU UE F1AP ID, replace - * old C-RNTI/PCI with new C-RNTI/PCI". So we delete the new contexts - * below, then change the C-RNTI of the old one to the new one */ + * old C-RNTI/PCI with new C-RNTI/PCI". Below, we do the inverse: we keep + * the new UE context (with new C-RNTI), but set up everything to reuse the + * old config. */ NR_UE_info_t *oldUE = find_nr_UE(&mac->UE_info, *dl_rrc->old_gNB_DU_ue_id); DevAssert(oldUE); pthread_mutex_lock(&mac->sched_lock); @@ -564,6 +619,9 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) UE->CellGroup->spCellConfig = NULL; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; + uid_t temp_uid = UE->uid; + UE->uid = oldUE->uid; + oldUE->uid = temp_uid; configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); nr_mac_prepare_cellgroup_update(mac, UE, oldUE->CellGroup); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 26a24c203e060d26a7a1c3168c4b0d6a6e2f4c9d..e3437f3c9a72fbf9737e2da8fb4a9a3f98b9b0ba 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -536,6 +536,11 @@ typedef struct NR_UE_ul_harq { NR_sched_pusch_t sched_pusch; } NR_UE_ul_harq_t; +typedef struct NR_QoS_config_s { + uint64_t fiveQI; + uint64_t priority; +} NR_QoS_config_t; + /*! \brief scheduling control information set through an API */ #define MAX_CSI_REPORTS 48 typedef struct { @@ -635,6 +640,9 @@ typedef struct { /// sri, ul_ri and tpmi based on SRS nr_srs_feedback_t srs_feedback; nssai_t dl_lc_nssai[NR_MAX_NUM_LCID]; + + // Information about the QoS configuration for each LCID/DRB + NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2) } NR_UE_sched_ctrl_t; typedef struct { diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index c9bbc6cd052eecc06fdc1c824281ba4c9eae884c..412a974406fbfd0c44c8f8b40c6e0d9d286f86e8 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -53,8 +53,8 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); for (int j=0; j < drb->numQosFlow2Setup; j++) { - asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, id); - *id = drb->qosFlows[j].id; + asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi); + *qfi = drb->qosFlows[j].qfi; } sdap_config->mappedQoS_FlowsToRelease = NULL; @@ -164,8 +164,11 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) DRB_nGRAN_setup_t *resp_drb = &resp_pdu->DRBnGRanList[0]; resp_drb->id = req_drb->id; resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; - for (int k = 0; k < resp_drb->numQosFlowSetup; k++) - resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id; + for (int k = 0; k < resp_drb->numQosFlowSetup; k++) { + const qos_flow_to_setup_t *qosflow2Setup = &req_drb->qosFlows[k]; + qos_flow_setup_t *qosflowSetup = &resp_drb->qosFlows[k]; + qosflowSetup->qfi = qosflow2Setup->qfi; + } // GTP tunnel for N3/to core gtpv1u_gnb_create_tunnel_resp_t resp_n3 = {0}; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index db57aa63f0a7b1c5484030f789af53265af03fcc..96444e5b1058e40d2c8101405d757adc2eb64707 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1093,12 +1093,11 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering) +void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_config, NR_SDAP_Config_t *sdap_config) { - /* The enabling/disabling of ciphering or integrity protection - * can be changed only by releasing and adding the DRB - * (so not by reconfiguring). - */ + // The enabling/disabling of ciphering or integrity protection + // can be changed only by releasing and adding the DRB + // (so not by reconfiguring). nr_pdcp_manager_lock(nr_pdcp_ue_manager); nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *drb = nr_pdcp_get_rb(ue, drb_id, false); @@ -1107,8 +1106,33 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering) nr_pdcp_manager_unlock(nr_pdcp_ue_manager); return; } - int decoded_t_reordering = decode_t_reordering(t_Reordering); - drb->t_reordering = decoded_t_reordering; + if (pdcp_config) { + if (pdcp_config->t_Reordering) + drb->t_reordering = decode_t_reordering(*pdcp_config->t_Reordering); + else + drb->t_reordering = -1; + struct NR_PDCP_Config__drb *drb_config = pdcp_config->drb; + if (drb_config) { + if (drb_config->discardTimer) + drb->discard_timer = decode_discard_timer(*drb_config->discardTimer); + bool size_set = false; + if (drb_config->pdcp_SN_SizeUL) { + drb->sn_size = decode_sn_size_ul(*drb_config->pdcp_SN_SizeUL); + size_set = true; + } + if (drb_config->pdcp_SN_SizeDL) { + int size = decode_sn_size_dl(*drb_config->pdcp_SN_SizeDL); + AssertFatal(!size_set || (size == drb->sn_size), + "SN sizes must be the same. dl=%d, ul=%d", + size, drb->sn_size); + drb->sn_size = size; + } + } + } + if (sdap_config) { + // nr_reconfigure_sdap_entity + AssertFatal(false, "Function to reconfigure SDAP entity not implemented yet\n"); + } nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } @@ -1131,6 +1155,7 @@ void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id) nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *drb = ue->drb[drb_id - 1]; if (drb) { + nr_sdap_release_drb(ue_id, drb_id, drb->pdusession_id); drb->release_entity(drb); drb->delete_entity(drb); ue->drb[drb_id - 1] = NULL; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 05e18c23c237b420dba3f248e9376f955fed0c1e..ea88fbfb1840f78db130ec48d22cbcfa780fb240 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -69,10 +69,11 @@ void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag); void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id); void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering); -void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, long t_Reordering); +void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_config, NR_SDAP_Config_t *sdap_config); void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id); void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id); + void add_srb(int is_gnb, ue_id_t rntiMaybeUEid, struct NR_SRB_ToAddMod *s, diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1d331b6340b5e722fcdd8327c5413620b7eda403..d967d3623f2ed569b15f35549acbcd4094a2ccaf 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2035,6 +2035,17 @@ unsigned int mask_flip(unsigned int x) { return((((x>>8) + (x<<8))&0xffff)>>6); } +static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession) +{ + pdusession_t *pdu = &pduSession->param; + for (int i = 0; i < pdu->nb_qos; i++) { + if (qfi == pdu->qos[i].qfi) + return &pdu->qos[i]; + } + AssertFatal(1 == 0, "The pdu session %d does not contain a qos flow with qfi = %d\n", pdu->pdusession_id, qfi); + return NULL; +} + void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance) { gNB_RRC_INST *rrc = RC.nrrrc[0]; @@ -2068,12 +2079,34 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, resp->pduSession[0].id, false); DevAssert(RRC_pduSession); for (int i = 0; i < nb_drb; i++) { + DRB_nGRAN_setup_t *drb_config = &resp->pduSession[0].DRBnGRanList[i]; drbs[i].drb_id = resp->pduSession[0].DRBnGRanList[i].id; drbs[i].rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; - drbs[i].up_ul_tnl[0].tl_address = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress; + drbs[i].up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd; - drbs[i].up_ul_tnl[0].teid = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId; + drbs[i].up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; drbs[i].up_ul_tnl_length = 1; + + /* pass QoS info to MAC */ + int nb_qos_flows = drb_config->numQosFlowSetup; + drbs[i].drb_info.flows_to_be_setup_length = nb_qos_flows; + drbs[i].drb_info.flows_mapped_to_drb = (f1ap_flows_mapped_to_drb_t *)calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t)); + AssertFatal(drbs[i].drb_info.flows_mapped_to_drb, "could not allocate memory\n"); + for (int j = 0; j < nb_qos_flows; j++) { + drbs[i].drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi; + + pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession); + f1ap_qos_characteristics_t *qos_char = &drbs[i].drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics; + if (in_qos_char->fiveQI_type == dynamic) { + qos_char->qos_type = dynamic; + qos_char->dynamic.fiveqi = in_qos_char->fiveQI; + qos_char->dynamic.qos_priority_level = in_qos_char->qos_priority; + } else { + qos_char->qos_type = non_dynamic; + qos_char->non_dynamic.fiveqi = in_qos_char->fiveQI; + qos_char->non_dynamic.qos_priority_level = in_qos_char->qos_priority; + } + } /* pass NSSAI info to MAC */ drbs[i].nssai = RRC_pduSession->param.nssai; } @@ -2269,7 +2302,11 @@ void *rrc_gnb_task(void *args_p) { itti_receive_msg(TASK_RRC_GNB, &msg_p); const char *msg_name_p = ITTI_MSG_NAME(msg_p); instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); - LOG_D(NR_RRC, "Received Msg %s\n", msg_name_p); + LOG_D(NR_RRC, + "RRC GNB Task Received %s for instance %ld from task %s\n", + ITTI_MSG_NAME(msg_p), + ITTI_MSG_DESTINATION_INSTANCE(msg_p), + ITTI_MSG_ORIGIN_NAME(msg_p)); switch (ITTI_MSG_ID(msg_p)) { case TERMINATE_MESSAGE: LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index f6059a91a9181ec89ddf39af8605092631fb3f8d..b659ccc2f870c85e87112b64108f319656fcee61 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -68,6 +68,7 @@ #include "NGAP_QosFlowSetupRequestItem.h" #include "NGAP_QosFlowAddOrModifyRequestItem.h" #include "NGAP_NonDynamic5QIDescriptor.h" +#include "NGAP_Dynamic5QIDescriptor.h" #include "conversions.h" #include "RRC/NR/rrc_gNB_radio_bearers.h" @@ -263,10 +264,15 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) // Set the QOS informations session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics; + AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - if (qosChar->choice.nonDynamic5QI != NULL) { - session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; - } + AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); + session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; + } else { + AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); + session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority; @@ -820,15 +826,25 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins drb->numQosFlow2Setup = session->nb_qos; for (int k=0; k < drb->numQosFlow2Setup; k++) { - qos_flow_to_setup_t *qos = drb->qosFlows + k; - - qos->id = session->qos[k].qfi; - qos->fiveQI = session->qos[k].fiveQI; - qos->fiveQI_type = session->qos[k].fiveQI_type; + qos_flow_to_setup_t *qos_flow = drb->qosFlows + k; + pdusession_level_qos_parameter_t *qos_session = session->qos + k; + + qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; + qos_flow->qfi = qos_session->qfi; + qos_char->qos_type = qos_session->fiveQI_type; + if (qos_char->qos_type == dynamic) { + qos_char->dynamic.fiveqi = qos_session->fiveQI; + qos_char->dynamic.qos_priority_level = qos_session->qos_priority; + } else { + qos_char->non_dynamic.fiveqi = qos_session->fiveQI; + qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority; + } - qos->qoSPriorityLevel = session->qos[k].allocation_retention_priority.priority_level; - qos->pre_emptionCapability = session->qos[k].allocation_retention_priority.pre_emp_capability; - qos->pre_emptionVulnerability = session->qos[k].allocation_retention_priority.pre_emp_vulnerability; + ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority; + ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority; + rent_priority->priority_level = rent_priority_in->priority_level; + rent_priority->preemption_capability = rent_priority_in->pre_emp_capability; + rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability; } } } @@ -854,12 +870,15 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s // Set the QOS informations session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics; + AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { - if (qosChar->choice.nonDynamic5QI != NULL) { - session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; - } - } else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) { - // TODO + AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); + session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; + } else { + AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); + session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 0617f79a836ccecdff5dca118124fc2b3f436172..389f849b2049a2a0938fb99e2c15159b8bb67cd3 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1256,8 +1256,9 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, if (rrcNB->status_DRBs[DRB_id] == RB_ESTABLISHED) { AssertFatal(drb->reestablishPDCP == NULL, "reestablishPDCP not yet implemented\n"); AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n"); - if (drb->pdcp_Config && drb->pdcp_Config->t_Reordering) - nr_pdcp_reconfigure_drb(rnti, DRB_id, *drb->pdcp_Config->t_Reordering); + NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL; + if (drb->pdcp_Config || sdap_Config) + nr_pdcp_reconfigure_drb(rnti, DRB_id, drb->pdcp_Config, sdap_Config); if (drb->cnAssociation) AssertFatal(drb->cnAssociation->choice.sdap_Config == NULL, "SDAP reconfiguration not yet implemented\n"); } else { diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 6fdd8eb54ad987b7df0b8ed98ea1e5baec2c06cf..f3f83158394da9d1fc6cbf8b6a66316291928a4f 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -468,6 +468,21 @@ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id) return NULL; } +void nr_sdap_release_drb(ue_id_t ue_id, int drb_id, int pdusession_id) +{ + // remove all QoS flow to DRB mappings associated with the released DRB + nr_sdap_entity_t *sdap = nr_sdap_get_entity(ue_id, pdusession_id); + if (sdap) { + for (int i = 0; i < SDAP_MAX_QFI; i++) { + if (sdap->qfi2drb_table[i].drb_id == drb_id) + sdap->qfi2drb_table[i].drb_id = SDAP_NO_MAPPING_RULE; + } + } + else + LOG_E(SDAP, "Couldn't find a SDAP entity associated with PDU session ID %d\n", + pdusession_id); +} + bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) { nr_sdap_entity_t *entityPtr = sdap_info.sdap_entity_llist; diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index 41a52c083b65da1099bbda921ac885dfecdbea77..07d62a4746b80bc8c52410d7982a466d42c736ac 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -169,6 +169,8 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, bool has_sdap_rx, bool has_sdap /* Entity Handling Related Functions */ nr_sdap_entity_t *nr_sdap_get_entity(ue_id_t ue_id, int pdusession_id); +void nr_sdap_release_drb(ue_id_t ue_id, int drb_id, int pdusession_id); + /** * @brief Function to delete a single SDAP Entity based on the ue_id and pdusession_id. * @note 1. SDAP entities may have the same ue_id. diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index 015b2a8f9e5dfa3fd115826b906e49226ba23434..f83f1138b6058ba073e1a124a8725fab158b0daa 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -52,12 +52,14 @@ #include <openair1/SIMULATION/ETH_TRANSPORT/proto.h> #include "openair2/SDAP/nr_sdap/nr_sdap.h" #include "openair3/SECU/nas_stream_eia2.h" +#include "openair3/UTILS/conversions.h" uint8_t *registration_request_buf; uint32_t registration_request_len; extern char *baseNetAddress; extern uint16_t NB_UE_INST; static nr_ue_nas_t nr_ue_nas = {0}; +static nr_nas_msg_snssai_t nas_allowed_nssai[8]; static int nas_protected_security_header_encode( char *buffer, @@ -778,7 +780,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi initialNasMsg->data[2 + i] = mac[i]; } -static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg) +static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) { //wait send RegistrationComplete usleep(100*150); @@ -790,11 +792,11 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * uint8_t *req_buffer = malloc(req_length); pdu_session_establishment_request_msg pdu_session_establish; pdu_session_establish.protocoldiscriminator = FGS_SESSION_MANAGEMENT_MESSAGE; - pdu_session_establish.pdusessionid = 10; + pdu_session_establish.pdusessionid = pdu_req->pdusession_id; pdu_session_establish.pti = 1; pdu_session_establish.pdusessionestblishmsgtype = FGS_PDU_SESSION_ESTABLISHMENT_REQ; pdu_session_establish.maxdatarate = 0xffff; - pdu_session_establish.pdusessiontype = 0x91; + pdu_session_establish.pdusessiontype = pdu_req->pdusession_type; encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); @@ -827,22 +829,19 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; size += (2+req_length); - mm_msg->uplink_nas_transport.pdusessionid = 10; + mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdusession_id; mm_msg->uplink_nas_transport.requesttype = 1; size += 3; - const bool has_nssai_sd = nas->uicc->nssai_sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 + const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; mm_msg->uplink_nas_transport.snssai.length = nssai_len; //Fixme: it seems there are a lot of memory errors in this: this value was on the stack, // but pushed in a itti message to another thread // this kind of error seems in many places in 5G NAS mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); - mm_msg->uplink_nas_transport.snssai.value[0] = nas->uicc->nssai_sst; - if (has_nssai_sd) { - mm_msg->uplink_nas_transport.snssai.value[1] = (nas->uicc->nssai_sd >> 16) & 0xFF; - mm_msg->uplink_nas_transport.snssai.value[2] = (nas->uicc->nssai_sd >> 8) & 0xFF; - mm_msg->uplink_nas_transport.snssai.value[3] = (nas->uicc->nssai_sd) & 0xFF; - } + mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->sst; + if (has_nssai_sd) + INT24_TO_BUFFER(pdu_req->sd, &mm_msg->uplink_nas_transport.snssai.value[1]); size += 1 + 1 + nssai_len; int dnnSize=strlen(nas->uicc->dnnStr); mm_msg->uplink_nas_transport.dnn.value=calloc(1,dnnSize+1); @@ -912,6 +911,120 @@ static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *i itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); } +static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t *buf, const uint32_t len) +{ + int nssai_cnt = 0; + const uint8_t *end = buf + len; + while (buf < end) { + const int length = *buf++; + nr_nas_msg_snssai_t *nssai = nssaiList + nssai_cnt; + nssai->sd = 0xffffff; + + switch (length) { + case 1: + nssai->sst = *buf++; + nssai_cnt++; + break; + + case 2: + nssai->sst = *buf++; + nssai->hplmn_sst = *buf++; + nssai_cnt++; + break; + + case 4: + nssai->sst = *buf++; + nssai->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai_cnt++; + break; + + case 5: + nssai->sst = *buf++; + nssai->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai->hplmn_sst = *buf++; + nssai_cnt++; + break; + + case 8: + nssai->sst = *buf++; + nssai->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai->hplmn_sst = *buf++; + nssai->hplmn_sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai_cnt++; + break; + + default: + LOG_E(NAS, "UE received unknown length in an allowed S-NSSAI\n"); + break; + } + } +} + +/* Extract Allowed NSSAI from Regestration Accept according to + 3GPP TS 24.501 Table 8.2.7.1.1 +*/ +static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_buffer, const uint32_t pdu_length) +{ + if ((pdu_buffer == NULL) || (pdu_length <= 0)) + return; + + const uint8_t *end = pdu_buffer + pdu_length; + if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) { + pdu_buffer += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; + } + + pdu_buffer += 1 + 1 + 1 + 2; // Mandatory fields offset + /* optional fields */ + while (pdu_buffer < end) { + const int type = *pdu_buffer++; + int length = 0; + switch (type) { + case 0x77: // 5GS mobile identity + pdu_buffer += ntoh_int16_buf(pdu_buffer) + sizeof(uint16_t); + break; + + case 0x4A: // PLMN list + case 0x54: // 5GS tracking area identity + pdu_buffer += *pdu_buffer + 1; // offset length + 1 byte which contains the length + break; + + case 0x15: // allowed NSSAI + length = *pdu_buffer++; + parse_allowed_nssai(nssai, pdu_buffer, length); + break; + + default: + LOG_W(NAS, "This NAS IEI is not handled when extracting list of allowed NSSAI\n"); + pdu_buffer = end; + break; + } + } +} + +static void request_default_pdusession(int instance, int nssai_idx) +{ + MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, 0, NAS_PDU_SESSION_REQ); + NAS_PDU_SESSION_REQ(message_p).pdusession_id = 10; /* first or default pdu session */ + NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; + NAS_PDU_SESSION_REQ(message_p).sst = nas_allowed_nssai[nssai_idx].sst; + NAS_PDU_SESSION_REQ(message_p).sd = nas_allowed_nssai[nssai_idx].sd; + itti_send_msg_to_task(TASK_NAS_NRUE, instance, message_p); +} + +static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[8], const nr_ue_nas_t *nas) +{ + for (int i = 0; i < 8; i++) { + const nr_nas_msg_snssai_t *nssai = allowed_nssai + i; + if ((nas->uicc->nssai_sst == nssai->sst) && (nas->uicc->nssai_sd == nssai->sd)) + return i; + } + return -1; +} + void *nas_nrue_task(void *args_p) { nr_ue_nas.uicc = checkUicc(0); @@ -975,6 +1088,18 @@ void *nas_nrue(void *args_p) /* TODO not processed by NAS currently */ break; + case NAS_PDU_SESSION_REQ: { + as_nas_info_t pduEstablishMsg = {0}; + nas_pdu_session_req_t *pduReq = &NAS_PDU_SESSION_REQ(msg_p); + nr_ue_nas_t *nas = get_ue_nas_info(0); + generatePduSessionEstablishRequest(nas, &pduEstablishMsg, pduReq); + if (pduEstablishMsg.length > 0) { + send_nas_uplink_data_req(instance, &pduEstablishMsg); + LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + } + break; + } + case NAS_CONN_ESTABLI_CNF: { LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", @@ -990,6 +1115,7 @@ void *nas_nrue(void *args_p) LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); nr_ue_nas_t *nas = get_ue_nas_info(0); decodeRegistrationAccept(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length, nas); + get_allowed_nssai(nas_allowed_nssai, pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); as_nas_info_t initialNasMsg = {0}; generateRegistrationComplete(nas, &initialNasMsg, NULL); @@ -998,11 +1124,11 @@ void *nas_nrue(void *args_p) LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } - as_nas_info_t pduEstablishMsg = {0}; - generatePduSessionEstablishRequest(nas, &pduEstablishMsg); - if (pduEstablishMsg.length > 0) { - send_nas_uplink_data_req(instance, &pduEstablishMsg); - LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + const int nssai_idx = get_user_nssai_idx(nas_allowed_nssai, nas); + if (nssai_idx < 0) { + LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); + } else { + request_default_pdusession(instance, nssai_idx); } } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { capture_pdu_session_establishment_accept_msg(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length); @@ -1081,12 +1207,11 @@ void *nas_nrue(void *args_p) send_nas_uplink_data_req(instance, &initialNasMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } - - as_nas_info_t pduEstablishMsg = {0}; - generatePduSessionEstablishRequest(nas, &pduEstablishMsg); - if (pduEstablishMsg.length > 0) { - send_nas_uplink_data_req(instance, &pduEstablishMsg); - LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(PduSessionEstablishRequest)\n"); + const int nssai_idx = get_user_nssai_idx(nas_allowed_nssai, nas); + if (nssai_idx < 0) { + LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); + } else { + request_default_pdusession(instance, nssai_idx); } break; case FGS_DEREGISTRATION_ACCEPT: diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.h b/openair3/NAS/NR_UE/nr_nas_msg_sim.h index fa4911c738238ae4f1597c5c16770ae49490277e..b1a1d25d1e2a6a58d5923854c4d71d6712db4516 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.h +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.h @@ -73,6 +73,14 @@ #define PAYLOAD_CONTAINER_LENGTH_MIN 3 #define PAYLOAD_CONTAINER_LENGTH_MAX 65537 +/* List of allowed NSSAI from NAS messaging. */ +typedef struct { + int sst; + int hplmn_sst; + int sd; + int hplmn_sd; +} nr_nas_msg_snssai_t; + /* Security Key for SA UE */ typedef struct { uint8_t kausf[32]; diff --git a/openair3/UTILS/conversions.h b/openair3/UTILS/conversions.h index ad84ecf0e05d230649f69df5b5a6d64d0504249b..2620d106a05e6f6f7a7f8fd946f570bae7795291 100644 --- a/openair3/UTILS/conversions.h +++ b/openair3/UTILS/conversions.h @@ -34,13 +34,19 @@ (((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8) # define ntoh_int32_buf(bUF) \ - ((*(bUF)) << 24) | ((*((bUF) + 1)) << 16) | ((*((bUF) + 2)) << 8) \ - | (*((bUF) + 3)) + ((*((uint8_t*)bUF)) << 24) | ((*((uint8_t*)bUF + 1)) << 16) | ((*((uint8_t*)bUF + 2)) << 8) \ + | (*((uint8_t*)bUF + 3)) #else # define hton_int32(x) (x) # define hton_int16(x) (x) #endif +#define ntoh_int24_buf(bUF) \ + ((*(uint8_t*)bUF << 16) | ((*((uint8_t*)bUF + 1)) << 8) | (*((uint8_t*)bUF + 2))) + +#define ntoh_int16_buf(bUF) \ + ((*((uint8_t*)bUF) << 8) | (*((uint8_t*)bUF + 1))) + #define IN_ADDR_TO_BUFFER(X,bUFF) INT32_TO_BUFFER((X).s_addr,(char*)bUFF) #define IN6_ADDR_TO_BUFFER(X,bUFF) \