Merge branch 'integration_2023_w49' into 'develop'
Integration: 2023.w49 See merge request oai/openairinterface5g!2470 * !2264 Improvements in f1ap for qos * !2377 Store allowed NSSAIs from NAS message * !2462 Hotfix: swap UIDs after RRCReestablishment * !2449 Improve performance of polar initialization * !2469 handling configuration of MAC-CellGroupConfig at UE * !2395 `nr_generate_pdsch()` clean up and little performance improves * !2461 CI: add FDD test to SA B200 pipeline * !2424 Improvements in SDAP RRC management
This commit is contained in:
+2
-6
@@ -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";
|
||||
};
|
||||
@@ -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";
|
||||
};
|
||||
@@ -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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = 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;
|
||||
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;
|
||||
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.
|
||||
// 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;
|
||||
|
||||
|
||||
@@ -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))) );
|
||||
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);
|
||||
}
|
||||
}
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+40
-23
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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_flow_to_setup_t *qos_flow = drb->qosFlows + k;
|
||||
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
|
||||
|
||||
qos->id = session->qos[k].qfi;
|
||||
qos->fiveQI = session->qos[k].fiveQI;
|
||||
qos->fiveQI_type = session->qos[k].fiveQI_type;
|
||||
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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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) \
|
||||
|
||||
Reference in New Issue
Block a user