Commit 790c3b99 authored by Robert Schmidt's avatar Robert Schmidt

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
parents c5aeaf03 5249dd96
......@@ -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";
};
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 = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1;
bitUpdated[currentBit][0]=1;
updateCrcChecksum2(polarParams->crcParityBits, 2*listSize, crcChecksum,
polarParams->K, polarParams->crcParityBits, extended_crc_generator_matrix,
currentListSize, nonFrozenBit, polarParams->crcParityBits);
currentListSize*=2;
for (int i = 0; i < currentListSize; i++) {
bit[currentBit][0][i] = 0;
crcState[i + currentListSize] = crcState[i];
}
//Keep only the best "listSize" number of entries.
for (int i = currentListSize; i < 2 * currentListSize; i++)
bit[currentBit][0][i] = 1;
bitUpdated[currentBit][0] = 1;
updateCrcChecksum2(polarParams->crcParityBits,
2 * listSize,
crcChecksum,
polarParams->K,
polarParams->crcParityBits,
extended_crc_generator_matrix,
currentListSize,
nonFrozenBit,
polarParams->crcParityBits);
currentListSize *= 2;
// Keep only the best "listSize" number of entries.
if (currentListSize > listSize) {
for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i;
for (uint8_t i = 0; i < 2 * listSize; i++)
listIndex[i] = i;
nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize);
//sort listIndex[listSize, ..., 2*listSize-1] in descending order.
// sort listIndex[listSize, ..., 2*listSize-1] in descending order.
uint8_t swaps, tempInd;
for (uint8_t i = 0; i < listSize; i++) {
swaps = 0;
for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) {
if (listIndex[j+1] > listIndex[j]) {
for (uint8_t j = listSize; j < (2 * listSize - i) - 1; j++) {
if (listIndex[j + 1] > listIndex[j]) {
tempInd = listIndex[j];
listIndex[j] = listIndex[j + 1];
listIndex[j + 1] = tempInd;
......@@ -196,8 +205,8 @@ int8_t polar_decoder(double *input,
for (int k=(listSize-1); k>0; k--) {
for (int i=0; i<polarParams->N; i++) {
for (int j=0; j<(polarParams->n+1); j++) {
bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]];
llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]];
bit[i][j][listIndex[(2 * listSize - 1) - k]] = bit[i][j][listIndex[k]];
llr[i][j][listIndex[(2 * listSize - 1) - k]] = llr[i][j][listIndex[k]];
}
}
}
......@@ -285,7 +294,8 @@ int8_t polar_decoder(double *input,
for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) {
if ( crcState[listIndex[i]] == 1 ) {
for (int j = 0; j < polarParams->N; j++) polarParams->nr_polar_U[j]=bit[j][0][listIndex[i]];
for (int j = 0; j < polarParams->N; j++)
polarParams->nr_polar_U[j] = bit[j][0][listIndex[i]];
//Extract the information bits (û to ĉ)
nr_polar_info_bit_extraction(polarParams->nr_polar_U, polarParams->nr_polar_CPrime, polarParams->information_bit_pattern, polarParams->N);
......@@ -626,7 +636,7 @@ uint32_t polar_decoder_int16(int16_t *input,
printf("\n");
#endif
int16_t d_tilde[polarParams->N];// = malloc(sizeof(double) * polarParams->N);
int16_t d_tilde[polarParams->N];
nr_polar_rate_matching_int16(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength, polarParams->i_bil);
for (int i=0; i<polarParams->N; i++) {
......@@ -687,14 +697,9 @@ uint32_t polar_decoder_int16(int16_t *input,
uint64_t B[4] = {0};
if (polarParams->K<65) {
B[0] = polarParams->B_tab0[0][Cprimebyte[0]] |
polarParams->B_tab0[1][Cprimebyte[1]] |
polarParams->B_tab0[2][Cprimebyte[2]] |
polarParams->B_tab0[3][Cprimebyte[3]] |
polarParams->B_tab0[4][Cprimebyte[4]] |
polarParams->B_tab0[5][Cprimebyte[5]] |
polarParams->B_tab0[6][Cprimebyte[6]] |
polarParams->B_tab0[7][Cprimebyte[7]];
B[0] = polarParams->B_tab0[0][Cprimebyte[0]] | polarParams->B_tab0[1][Cprimebyte[1]] | polarParams->B_tab0[2][Cprimebyte[2]]
| polarParams->B_tab0[3][Cprimebyte[3]] | polarParams->B_tab0[4][Cprimebyte[4]] | polarParams->B_tab0[5][Cprimebyte[5]]
| polarParams->B_tab0[6][Cprimebyte[6]] | polarParams->B_tab0[7][Cprimebyte[7]];
} else if (polarParams->K<129) {
int len = polarParams->K/8;
......
......@@ -45,20 +45,23 @@ static inline void updateBit(uint8_t listSize,
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen])
{
uint16_t offset = ( xlen/(pow(2,(ylen-col))) );
for (uint8_t i=0; i<listSize; i++) {
if (( (row) % (2*offset) ) >= offset ) {
if (bitU[row][col-1]==0) updateBit(listSize, row, (col-1), xlen, ylen, zlen, bit, bitU);
bit[row][col][i] = bit[row][col-1][i];
} else {
if (bitU[row][col-1]==0) updateBit(listSize, row, (col-1), xlen, ylen, zlen, bit, bitU);
if (bitU[row+offset][col-1]==0) updateBit(listSize, (row+offset), (col-1), xlen, ylen, zlen, bit, bitU);
bit[row][col][i] = ( (bit[row][col-1][i]+bit[row+offset][col-1][i]) % 2);
}
}
uint16_t offset = (xlen / (pow(2, (ylen - col))));
for (uint8_t i = 0; i < listSize; i++) {
if (((row) % (2 * offset)) >= offset) {
if (bitU[row][col - 1] == 0)
updateBit(listSize, row, (col - 1), xlen, ylen, zlen, bit, bitU);
bit[row][col][i] = bit[row][col - 1][i];
} else {
if (bitU[row][col - 1] == 0)
updateBit(listSize, row, (col - 1), xlen, ylen, zlen, bit, bitU);
if (bitU[row + offset][col - 1] == 0)
updateBit(listSize, (row + offset), (col - 1), xlen, ylen, zlen, bit, bitU);
bit[row][col][i] = ((bit[row][col - 1][i] + bit[row + offset][col - 1][i]) % 2);
}
}
bitU[row][col]=1;
bitU[row][col] = 1;
}
static inline void computeLLR(uint16_t row,
......@@ -75,35 +78,38 @@ static inline void computeLLR(uint16_t row,
llr[row][col][i] = log((exp(a + b) + 1) / (exp(a) + exp(b))); //eq. (8a)
}
void updateLLR(uint8_t listSize,
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
double llr[xlen][ylen][zlen],
uint8_t llrU[xlen][ylen],
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen]
)
uint16_t row,
uint16_t col,
uint16_t xlen,
uint8_t ylen,
int zlen,
double llr[xlen][ylen][zlen],
uint8_t llrU[xlen][ylen],
uint8_t bit[xlen][ylen][zlen],
uint8_t bitU[xlen][ylen])
{
uint16_t offset = (xlen/(pow(2,(ylen-col-1))));
for (uint8_t i=0; i<listSize; i++) {
if (( (row) % (2*offset) ) >= offset ) {
if(bitU[row-offset][col]==0) updateBit(listSize, (row-offset), col, xlen, ylen, zlen, bit, bitU);
if(llrU[row-offset][col+1]==0) updateLLR(listSize, (row-offset), (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU );
if(llrU[row][col+1]==0) updateLLR(listSize, row, (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU);
llr[row][col][i] = (pow((-1),bit[row-offset][col][i])*llr[row-offset][col+1][i]) + llr[row][col+1][i];
} else {
if(llrU[row][col+1]==0) updateLLR(listSize, row, (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU );
if(llrU[row+offset][col+1]==0) updateLLR(listSize, (row+offset), (col+1), xlen, ylen, zlen, llr, llrU, bit, bitU );
computeLLR(row, col, i, offset, xlen, ylen, zlen, llr);
}
}
llrU[row][col]=1;
uint16_t offset = (xlen / (pow(2, (ylen - col - 1))));
for (uint8_t i = 0; i < listSize; i++) {
if ((row % (2 * offset)) >= offset) {
if (bitU[row - offset][col] == 0)
updateBit(listSize, (row - offset), col, xlen, ylen, zlen, bit, bitU);
if (llrU[row - offset][col + 1] == 0)
updateLLR(listSize, (row - offset), (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU);
if (llrU[row][col + 1] == 0)
updateLLR(listSize, row, (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU);
llr[row][col][i] = (pow((-1), bit[row - offset][col][i]) * llr[row - offset][col + 1][i]) + llr[row][col + 1][i];
} else {
if (llrU[row][col + 1] == 0)
updateLLR(listSize, row, (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU);
if (llrU[row + offset][col + 1] == 0)
updateLLR(listSize, (row + offset), (col + 1), xlen, ylen, zlen, llr, llrU, bit, bitU);
computeLLR(row, col, i, offset, xlen, ylen, zlen, llr);
}
}
llrU[row][col] = 1;
// printf("LLR (a %f, b %f): llr[%d][%d] %f\n",32*a,32*b,col,row,32*llr[col][row]);
// printf("LLR (a %f, b %f): llr[%d][%d] %f\n",32*a,32*b,col,row,32*llr[col][row]);
}
void updatePathMetric(double *pathMetric,
......
......@@ -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
This diff is collapsed.
......@@ -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 {
......
......@@ -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;
......
......@@ -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->id = session->qos[k].qfi;
qos->fiveQI = session->qos[k].fiveQI;
qos->fiveQI_type = session->qos[k].fiveQI_type;
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
qos_flow->qfi = qos_session->qfi;
qos_char->qos_type = qos_session->fiveQI_type;
if (qos_char->qos_type == dynamic) {
qos_char->dynamic.fiveqi = qos_session->fiveQI;
qos_char->dynamic.qos_priority_level = qos_session->qos_priority;
} else {
qos_char->non_dynamic.fiveqi = qos_session->fiveQI;
qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority;
}
qos->qoSPriorityLevel = session->qos[k].allocation_retention_priority.priority_level;
qos->pre_emptionCapability = session->qos[k].allocation_retention_priority.pre_emp_capability;
qos->pre_emptionVulnerability = session->qos[k].allocation_retention_priority.pre_emp_vulnerability;
ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
rent_priority->priority_level = rent_priority_in->priority_level;
rent_priority->preemption_capability = rent_priority_in->pre_emp_capability;
rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability;
}
}
}
......@@ -854,12 +870,15 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
if (qosChar->choice.nonDynamic5QI != NULL) {
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
}
} else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) {
// TODO
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = non_dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
......
......@@ -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.
......
This diff is collapsed.
......@@ -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) \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment