Commit 4d9ebf0a authored by Raymond Knopp's avatar Raymond Knopp

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

Conflicts:
	cmake_targets/CMakeLists.txt
	executables/nr-softmodem.c
	executables/nr-uesoftmodem.c
	openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
	openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
	openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
	openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
	openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
	openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
	openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
	openair2/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
	openair2/RRC/NR/rrc_gNB.c
	openair2/RRC/NR/rrc_gNB_NGAP.c
	openair2/RRC/NR_UE/rrc_UE.c
	openair3/NGAP/ngap_gNB.c
	openair3/NGAP/ngap_gNB_nas_procedures.c
parents c416e545 17d4c5c2
......@@ -25,4 +25,4 @@
]
}
]
}
\ No newline at end of file
}
This diff is collapsed.
#!/bin/bash
#/*
# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
# * contributor license agreements. See the NOTICE file distributed with
# * this work for additional information regarding copyright ownership.
# * The OpenAirInterface Software Alliance licenses this file to You under
# * the OAI Public License, Version 1.1 (the "License"); you may not use this file
# * except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.openairinterface.org/?page_id=698
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.
# *-------------------------------------------------------------------------------
# * For more information about the OpenAirInterface (OAI) Software Alliance:
# * contact@openairinterface.org
# */
function usage {
echo "OAI GitLab merge request applying script"
echo " Original Author: Raphael Defosseux"
echo ""
echo "Usage:"
echo "------"
echo ""
echo " checkGitLabMergeRequestLabels.sh [OPTIONS]"
echo ""
echo "Options:"
echo "------------------"
echo ""
echo " --mr-id ####"
echo " Specify the ID of the merge request."
echo ""
echo " --help OR -h"
echo " Print this help message."
echo ""
}
if [ $# -ne 2 ] && [ $# -ne 1 ]
then
echo "Syntax Error: not the correct number of arguments"
echo ""
usage
exit 1
fi
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-h|--help)
shift
usage
exit 0
;;
--mr-id)
MERGE_REQUEST_ID="$2"
shift
shift
;;
*)
echo "Syntax Error: unknown option: $key"
echo ""
usage
exit 1
esac
done
LABELS=`curl --silent "https://gitlab.eurecom.fr/api/v4/projects/oai%2Fopenairinterface5g/merge_requests/$MERGE_REQUEST_ID" | jq '.labels' || true`
IS_MR_BUILD_ONLY=`echo $LABELS | grep -c BUILD-ONLY || true`
IS_MR_CI=`echo $LABELS | grep -c CI || true`
IS_MR_4G=`echo $LABELS | grep -c 4G-LTE || true`
IS_MR_5G=`echo $LABELS | grep -c 5G-NR || true`
# First case: none is present! No CI
if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 0 ]
then
echo "NONE"
exit 0
fi
# Second case: Build-Only
if [ $IS_MR_BUILD_ONLY -eq 1 ]
then
echo "BUILD-ONLY"
exit 0
fi
# Third case: CI or 4G label --> Full CI run
if [ $IS_MR_4G -eq 1 ] || [ $IS_MR_CI -eq 1 ]
then
echo "FULL"
exit 0
fi
# Fourth case: 5G label
if [ $IS_MR_BUILD_ONLY -eq 0 ] && [ $IS_MR_CI -eq 0 ] && [ $IS_MR_4G -eq 0 ] && [ $IS_MR_5G -eq 1 ]
then
echo "SHORTEN-5G"
exit 0
fi
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
Num_Threads_PUSCH = 8
gNBs =
......@@ -251,6 +250,7 @@ L1s = (
{
num_cc = 1;
tr_n_preference = "local_mac";
pusch_proc_threads = 8;
}
);
......
......@@ -52,7 +52,7 @@
<testCase id="090102">
<class>Initialize_OAI_UE</class>
<desc>Initialize NR UE USRP</desc>
<Initialize_OAI_UE_args>--phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 75 --rrc_config_path . --dlsch-parallel 4 </Initialize_OAI_UE_args>
<Initialize_OAI_UE_args>--phy-test --usrp-args "addr=192.168.30.2,second_addr=192.168.50.2,clock_source=external,time_source=external" --ue-rxgain 50 --rrc_config_path . --dlsch-parallel 4 </Initialize_OAI_UE_args>
<air_interface>NR</air_interface>
</testCase>
......
......@@ -485,7 +485,6 @@ add_custom_target (
add_library(NR_RRC_LIB ${nr_rrc_h} ${nr_rrc_source}
${OPENAIR2_DIR}/RRC/NR/MESSAGES/asn1_msg.c
${OPENAIR2_DIR}/RRC/NR/nr_ngap_gNB.c
)
add_dependencies(NR_RRC_LIB nr_rrc_flag)
include_directories ("${NR_RRC_FULL_DIR}")
......@@ -1969,6 +1968,7 @@ set(NR_PDCP_SRC
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_ue_manager.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_drb_am.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c
${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_entity_srb.c
)
......@@ -2112,10 +2112,10 @@ set (MAC_NR_SRC_UE
${NR_UE_MAC_DIR}/mac_vars.c
${NR_UE_MAC_DIR}/main_ue_nr.c
${NR_UE_MAC_DIR}/nr_ue_procedures.c
${NR_UE_MAC_DIR}/nr_ue_scheduler.c
${NR_UE_MAC_DIR}/nr_ue_dci_configuration.c
${NR_UE_MAC_DIR}/nr_l1_helpers.c
${NR_UE_MAC_DIR}/nr_ra_procedures.c
${NR_UE_MAC_DIR}/rar_tools_nrUE.c
)
set (ENB_APP_SRC
......@@ -2135,7 +2135,23 @@ set (MCE_APP_SRC
${OPENAIR2_DIR}/MCE_APP/mce_app.c
${OPENAIR2_DIR}/MCE_APP/mce_config.c
)
set (MISC_NFAPI_LTE
${OPENAIR1_DIR}/SCHED/nfapi_lte_dummy.c
)
add_library(MISC_NFAPI_LTE_LIB
${MISC_NFAPI_LTE}
)
set (MISC_NFAPI_NR
${OPENAIR1_DIR}/SCHED/nfapi_nr_dummy.c
)
add_library(MISC_NFAPI_NR_LIB
${MISC_NFAPI_NR}
)
add_library(L2
${L2_SRC}
${MAC_SRC}
......@@ -2888,7 +2904,7 @@ add_dependencies(lte-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer)
target_link_libraries (lte-softmodem
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB LFDS7
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
-Wl,--end-group z dl)
......@@ -2929,7 +2945,7 @@ add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer coding params_l
target_link_libraries (ocp-enb
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON
PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB MISC_NFAPI_LTE_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 SIMU_COMMON
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB}
-Wl,--end-group z dl)
target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB})
......@@ -2999,7 +3015,7 @@ target_link_libraries (lte-uesoftmodem
-Wl,--start-group
RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB X2AP_LIB X2AP_ENB M2AP_LIB M2AP_ENB M3AP_LIB M3AP_ENB F1AP F1AP_LIB
GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
PHY_UE PHY_RU LFDS L2_UE L2_LTE LFDS7 SIMU_COMMON SIMU NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${ATLAS_LIBRARIES}
-Wl,--end-group z dl)
......@@ -3126,7 +3142,13 @@ target_link_libraries (nr-uesoftmodem
-Wl,--start-group
RRC_LIB NR_RRC_LIB NGAP_LIB NGAP_GNB SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB
PHY_COMMON PHY_NR_COMMON PHY_UE PHY_NR_UE PHY_RU LFDS NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
<<<<<<< HEAD
NFAPI_USER_LIB S1AP_LIB S1AP_ENB ${PROTO_AGENT_LIB} ${FSPT_MSG_LIB}
=======
NFAPI_USER_LIB MISC_NFAPI_NR_LIB S1AP_LIB S1AP_ENB
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES}
NFAPI_USER_LIB S1AP_LIB S1AP_ENB
>>>>>>> origin/develop
${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7 ${ATLAS_LIBRARIES} LIB_5GNAS_GNB
-Wl,--end-group z dl)
......
......@@ -1292,7 +1292,9 @@
(Test8: DMRS Type B, 3 DMRS, 2 PTRS, 3 Interpolated Symbols),
(Test9: SC-FDMA, 50 PRBs),
(Test10: SC-FDMA, 75 PRBs),
(Test11: SC-FDMA, 3 DMRS)</desc>
(Test11: SC-FDMA, 216 PRBs),
(Test12: SC-FDMA, 273 PRBs),
(Test13: SC-FDMA, 3 DMRS)</desc>
<pre_compile_prog></pre_compile_prog>
<compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
<compile_prog_args> --phy_simulators -c </compile_prog_args>
......@@ -1307,10 +1309,13 @@
-n100 -s5 -T 2 1 2 -U 2 0 2
-n100 -s5 -T 2 2 2 -U 2 1 2
-n100 -s5 -a4 -b8 -T 2 1 2 -U 2 1 3
-n100 -s20 -Z
-n100 -s20 -Z -r75
-n100 -s20 -Z -U 2 0 2</main_exec_args>
<tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11</tags>
-n100 -s2 -Z
-n100 -s2 -Z -r75
-n100 -s2 -Z -r216 -R217
-n100 -s2 -Z -r270 -R273
-n100 -s2 -Z -U 2 0 2</main_exec_args>
<tags>nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 nr_ulsim.test6 nr_ulsim.test7 nr_ulsim.test8 nr_ulsim.test9 nr_ulsim.test10 nr_ulsim.test11 nr_ulsim.test12 nr_ulsim.test13</tags>
<search_expr_true>PUSCH test OK</search_expr_true>
<search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
<nruns>3</nruns>
......
......@@ -43,7 +43,7 @@
#include "config_userapi.h"
#include "../utils/LOG/log.h"
#define CONFIG_SHAREDLIBFORMAT "libparams_%s.so"
#include "nfapi/oai_integration/vendor_ext.h"
int load_config_sharedlib(configmodule_interface_t *cfgptr) {
void *lib_handle;
......@@ -331,9 +331,10 @@ void end_configmodule(void) {
printf ("[CONFIG] free %u config value pointers\n",cfgptr->numptrs);
for(int i=0; i<cfgptr->numptrs ; i++) {
if (cfgptr->ptrs[i] != NULL) {
if (cfgptr->ptrs[i] != NULL && cfgptr->ptrsAllocated[i] == true) {
free(cfgptr->ptrs[i]);
cfgptr->ptrs[i]=NULL;
cfgptr->ptrsAllocated[i] = false;
}
}
......
......@@ -36,6 +36,8 @@
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "common/config/config_paramdesc.h"
#include "common/utils/T/T.h"
#define CONFIG_MAX_OOPT_PARAMS 10 // maximum number of parameters in the -O option (-O <cfgmode>:P1:P2...
......@@ -74,6 +76,7 @@ typedef struct configmodule_interface {
uint32_t numptrs;
uint32_t rtflags;
char *ptrs[CONFIG_MAX_ALLOCATEDPTRS];
bool ptrsAllocated[CONFIG_MAX_ALLOCATEDPTRS];
} configmodule_interface_t;
#ifdef CONFIG_LOADCONFIG_MAIN
......
......@@ -62,6 +62,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) {
if ( (cfgoptions->paramflags & PARAMFLAG_NOFREE) == 0) {
config_get_if()->ptrs[config_get_if()->numptrs] = (char *)ptr;
config_get_if()->ptrsAllocated[config_get_if()->numptrs] = true;
config_get_if()->numptrs++;
}
} else {
......@@ -82,7 +83,9 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) {
}
if (*ptr == NULL) {
*ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch
*ptr = malloc(length>40?length:40);
// LTS: dummy fix, waiting Francois full fix in 4G branch
// the issue is we don't know at this point the size we will get
if ( *ptr != NULL) {
memset(*ptr,0,length);
......
......@@ -346,6 +346,7 @@ int config_libconfig_init(char *cfgP[], int numP) {
libconfig_privdata.configfile = strdup((char *)cfgP[0]);
config_get_if()->numptrs=0;
memset(config_get_if()->ptrs,0,sizeof(void *) * CONFIG_MAX_ALLOCATEDPTRS);
memset(config_get_if()->ptrsAllocated, 0, sizeof(config_get_if()->ptrsAllocated));
/* Read the file. If there is an error, report it and exit. */
if(! config_read_file(&(libconfig_privdata.cfg), libconfig_privdata.configfile)) {
......
......@@ -88,16 +88,19 @@ int write_file_matlab(const char *fname,
void *data,
int length,
int dec,
char format)
unsigned int format)
{
FILE *fp=NULL;
int i;
AssertFatal((format&~MATLAB_RAW) <16,"");
if (data == NULL)
return -1;
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14) {
fp = fopen(fname,"a+");
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
......@@ -109,6 +112,32 @@ int write_file_matlab(const char *fname,
return(-1);
}
if ( (format&MATLAB_RAW) == MATLAB_RAW ) {
int sz[16]={sizeof(short), 2*sizeof(short),
sizeof(int), 2*sizeof(int),
sizeof(char), 2*sizeof(char),
sizeof(long long),
sizeof(double), 2*sizeof(double),
sizeof(unsigned char),
sizeof(short),
sizeof(short),
sizeof(short),
sizeof(short),
sizeof(short),
sizeof(short)
};
int eltSz= sz[format&~MATLAB_RAW];
if (dec==1)
fwrite(data, eltSz, length, fp);
else
for (i=0; i<length; i+=dec)
fwrite(data+i*eltSz, eltSz, 1, fp);
fclose(fp);
return(0);
}
if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14)
fprintf(fp,"%s = [",vname);
......@@ -214,6 +243,8 @@ int write_file_matlab(const char *fname,
case 12 : // case eren for log2_maxh real unsigned 8 bit
fprintf(fp,"%d \n",((unsigned char *)&data)[0]);
break;
default:
AssertFatal(false, "unknown dump format: %d\n", format);
}
if (format != 10 && format !=11 && format !=12 && format != 13 && format != 15) {
......
......@@ -336,7 +336,25 @@ typedef struct {
@param dec decimation level
@param format data format (0 = real 16-bit, 1 = complex 16-bit,2 real 32-bit, 3 complex 32-bit,4 = real 8-bit, 5 = complex 8-bit)
*/
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, char format);
#define MATLAB_RAW (1<<31)
#define MATLAB_SHORT 0
#define MATLAB_CSHORT 1
#define MATLAB_INT 2
#define MATLAB_CINT 3
#define MATLAB_INT8 4
#define MATLAB_CINT8 5
#define MATLAB_LLONG 6
#define MATLAB_DOUBLE 7
#define MATLAB_CDOUBLE 8
#define MATLAB_UINT8 9
#define MATLEB_EREN1 10
#define MATLEB_EREN2 11
#define MATLEB_EREN3 12
#define MATLAB_CSHORT_BRACKET1 13
#define MATLAB_CSHORT_BRACKET2 14
#define MATLAB_CSHORT_BRACKET3 15
int32_t write_file_matlab(const char *fname, const char *vname, void *data, int length, int dec, unsigned int format);
/*----------------macro definitions for reading log configuration from the config module */
#define CONFIG_STRING_LOG_PREFIX "log_config"
......
<table style="border-collapse: collapse; border: none;">
<tr style="border-collapse: collapse; border: none;">
<td style="border-collapse: collapse; border: none;">
<a href="http://www.openairinterface.org/">
<img src="./images/oai_final_logo.png" alt="" border=3 height=50 width=150>
</img>
</a>
</td>
<td style="border-collapse: collapse; border: none; vertical-align: center;">
<b><font size = "5">Running L3 ITTI simulator</font></b>
</td>
</tr>
</table>
This page is valid on the following branches:
- `develop` starting from tag `2020.w48`
# 1. Building the ITTI simulator.
The ITTI simulator is available directly from the standard build.
```bash
$ source oaienv
$ cd cmake_targets
$ sudo ./build_oai -x -w None -c -ittiSIM
```
# 2. Running the ITTI simulator.
The ITTI simulator establishes ITTI-threaded communication between the gNB RRC task and the UE RRC task.
This allows to test the sequence of NGAP/RRC/NAS messages.
The main limitations are:
- NAS is a simple stub that just sends and receives messages
- only initial Attach sequence
## 2.1. Starting the ITTI simulator
The ITTI simulator is able to run with a connected 5GC or without any.
The develop branch tag `2020.w48` only works RRC without 5GC connection.
```bash
$ sudo -E ./ran_build/build/nr-ittisim -O gnb.conf
```
......@@ -186,7 +186,7 @@ development], for FR2 does not exist yet.
3) allocate a CCE for the UE (and return if it is not possible)
4) Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS.
5) Mark used resources in vrb_map_UL.
* loop through all users: get a free HARQ PID using select_ul_harq_pid() and
* loop through all users: get a free HARQ PID and
update statistics. Fill nFAPI structures directly for PUSCH, and call
config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages.
......
......@@ -74,6 +74,7 @@ int config_sync_var=-1;
volatile int oai_exit = 0;
double cpuf;
uint16_t sf_ahead=4;
//uint16_t slot_ahead=6;
int otg_enabled;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
......
......@@ -84,7 +84,7 @@
#include "T.h"
#include "nfapi/oai_integration/vendor_ext.h"
//#define DEBUG_THREADS 1
//#define USRP_DEBUG 1
......@@ -137,6 +137,7 @@ void wakeup_prach_gNB(PHY_VARS_gNB *gNB, RU_t *ru, int frame, int subframe);
extern uint8_t nfapi_mode;
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void oai_slot_ind(uint16_t sfn, uint16_t slot);
extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset);
//#define TICK_TO_US(ts) (ts.diff)
......@@ -151,13 +152,14 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
// *******************************************************************
// NFAPI not yet supported for NR - this code has to be revised
if (nfapi_mode == 1) {
if (NFAPI_MODE == NFAPI_MODE_PNF) {
// I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
//add_subframe(&frame, &subframe, 4);
//oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
//LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe);
start_meas(&nfapi_meas);
oai_subframe_ind(frame_rx, slot_rx);
// oai_subframe_ind(frame_rx, slot_rx);
oai_slot_ind(frame_rx, slot_rx);
stop_meas(&nfapi_meas);
/*if (gNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus||
......@@ -873,10 +875,7 @@ void init_gNB_proc(int inst) {
gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
uint32_t num_threads_pusch;
paramdef_t PUSCHThreads[] = NUM_THREADS_DESC;
config_get( PUSCHThreads,sizeof(PUSCHThreads)/sizeof(paramdef_t),NULL);
int threadCnt = min(numCPU, num_threads_pusch);
int threadCnt = min(numCPU, gNB->pusch_proc_threads);
char ul_pool[80];
sprintf(ul_pool,"-1");
int s_offset = 0;
......
......@@ -114,6 +114,7 @@ int attach_rru(RU_t *ru);
int connect_rau(RU_t *ru);
uint16_t sf_ahead;
uint16_t slot_ahead;
uint16_t sl_ahead;
extern int emulate_rf;
......
......@@ -77,6 +77,7 @@
#define CONFIG_HLP_UE "Set the lte softmodem as a UE\n"
#define CONFIG_HLP_L2MONW "Enable L2 wireshark messages on localhost \n"
#define CONFIG_HLP_L2MONP "Enable L2 pcap messages on localhost \n"
#define CONFIG_HLP_MAC "Disable the MAC procedures at UE side (default is enabled)\n"
#define CONFIG_HLP_VCD "Enable VCD (generated file will is named openair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n"
#define CONFIG_HLP_TQFS "Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"
#define CONFIG_HLP_TPORT "tracer port\n"
......
......@@ -87,13 +87,13 @@ unsigned short config_frames[4] = {2,9,11,13};
#include "gnb_paramdef.h"
#include "f1ap_cu_task.h"
#include "f1ap_du_task.h"
#include "nfapi/oai_integration/vendor_ext.h"
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
uint8_t nfapi_mode = 0; // Default to monolithic mode
extern uint8_t nfapi_mode; // Default to monolithic mode
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
......@@ -836,7 +836,7 @@ if(!IS_SOFTMODEM_NOS1)
nr_read_config_and_init();
} else {
printf("No ITTI, Initializing L1\n");
RCconfig_L1();
RCconfig_NR_L1();
}
if (RC.nb_nr_inst > 0) {
......@@ -874,7 +874,7 @@ if(!IS_SOFTMODEM_NOS1)
usleep(1000);
if (nfapi_mode) {
if (NFAPI_MODE) {
printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
......@@ -882,7 +882,7 @@ if(!IS_SOFTMODEM_NOS1)
const char *nfapi_mode_str = "<UNKNOWN>";
switch(nfapi_mode) {
switch(NFAPI_MODE) {
case 0:
nfapi_mode_str = "MONOLITHIC";
break;
......@@ -902,7 +902,7 @@ if(!IS_SOFTMODEM_NOS1)
printf("NFAPI MODE:%s\n", nfapi_mode_str);
if (nfapi_mode==2) // VNF
if (NFAPI_MODE==NFAPI_MODE_VNF)
wait_nfapi_init("main?");
printf("START MAIN THREADS\n");
......@@ -931,10 +931,11 @@ if(!IS_SOFTMODEM_NOS1)
config_sync_var=0;
if (nfapi_mode==1) { // PNF
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}
if (NODE_IS_DU(node_type) || (node_type == ngran_gNB)) {
printf("wait RUs\n");
wait_RUs();
......@@ -951,6 +952,13 @@ if(!IS_SOFTMODEM_NOS1)
p.ru=RC.ru[0];
load_softscope("nr",&p);
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
} else {
printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
}
if (nfapi_mode != 1 && nfapi_mode != 2) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
......
......@@ -18,49 +18,16 @@
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "executables/thread-common.h"
#include "executables/nr-uesoftmodem.h"
#include "NR_MAC_UE/mac.h"
//#include "RRC/LTE/rrc_extern.h"
#include "PHY_INTERFACE/phy_interface_extern.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "fapi_nr_ue_l1.h"
#include "executables/nr-uesoftmodem.h"
#include "PHY/phy_extern_nr_ue.h"
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "NR_MAC_UE/mac_proto.h"
#include "RRC/NR_UE/rrc_proto.h"
#include "SCHED_NR_UE/phy_frame_config_nr.h"
#include "SCHED_NR_UE/defs.h"
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
#include "common/utils/LOG/log.h"
#include "common/utils/system.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "executables/nr-softmodem.h"
#include "T.h"
#ifdef XFORMS
#include "PHY/TOOLS/nr_phy_scope.h"
extern char do_forms;
#endif
// Missing stuff?
int next_ra_frame = 0;
module_id_t next_Mod_id = 0;
extern double cpuf;
//static nfapi_nr_config_request_t config_t;
//static nfapi_nr_config_request_t* config =&config_t;
/*
* NR SLOT PROCESSING SEQUENCE
*
......@@ -124,16 +91,12 @@ extern double cpuf;
#define DURATION_RX_TO_TX (6) /* For LTE, this duration is fixed to 4 and it is linked to LTE standard for both modes FDD/TDD */
#endif
#define FRAME_PERIOD 100000000ULL
#define DAQ_PERIOD 66667ULL
typedef enum {
pss=0,
pbch=1,
si=2
pss = 0,
pbch = 1,
si = 2
} sync_mode_t;
void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
uint8_t UE_id,
uint8_t abstraction_flag)
......@@ -258,7 +221,7 @@ static void UE_synch(void *arg) {
double rx_gain_off = 0;
nr_get_carrier_frequencies(&UE->frame_parms, &dl_carrier, &ul_carrier);
if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) {
if (nr_initial_sync(&syncD->proc, UE, 2) == 0) {
freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) +
round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
......@@ -394,26 +357,17 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
nr_downlink_indication_t dl_indication;
memset((void*)&dl_indication, 0, sizeof(dl_indication));
dl_indication.module_id = UE->Mod_id;
dl_indication.gNB_index = gNB_id;
dl_indication.cc_id = UE->CC_id;
dl_indication.frame = proc->frame_rx;
dl_indication.slot = proc->nr_slot_rx;
dl_indication.thread_id = proc->thread_id;
nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, gNB_id);
UE->if_inst->dl_indication(&dl_indication, NULL);
}
// Process Rx data for one sub-frame
#ifdef UE_SLOT_PARALLELISATION
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, no_relay, NULL );
#else
uint64_t a=rdtsc();
phy_procedures_nrUE_RX( UE, proc, 0, UE->mode,get_nrUE_params()->nr_dlsch_parallel);
LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_slot_rx, (rdtsc()-a)/3500);
//printf(">>> nr_ue_pdcch_procedures ended\n");
phy_procedures_nrUE_RX(UE, proc, gNB_id, get_nrUE_params()->nr_dlsch_parallel);
LOG_D(PHY, "In %s: slot %d, time %lu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc()-a)/3500);
#endif
if(IS_SOFTMODEM_NOS1){
......@@ -424,23 +378,6 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
}
}
// no UL for now
/*
if (UE->mac_enabled==1) {
// trigger L2 to run ue_scheduler thru IF module
// [TODO] mapping right after NR initial sync
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
UE->ul_indication.module_id = 0;
UE->ul_indication.gNB_index = 0;
UE->ul_indication.cc_id = 0;
UE->ul_indication.frame = proc->frame_rx;
UE->ul_indication.slot = proc->nr_slot_rx;
UE->ul_indication.thread_id = proc->thread_id;
UE->if_inst->ul_indication(&UE->ul_indication);
}
}
*/
}
/*!
......@@ -705,8 +642,7 @@ void *UE_thread(void *arg) {
UE->rx_offset_diff = computeSamplesShift(UE);
readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) -
UE->rx_offset_diff;
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)-
UE->rx_offset_diff;
writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff;
}
AssertFatal(readBlockSize ==
......@@ -765,14 +701,28 @@ void *UE_thread(void *arg) {
timing_advance = UE->timing_advance;
}
AssertFatal( writeBlockSize ==
int flags = 0;
int slot_tx_usrp = slot_nr + DURATION_RX_TO_TX - RX_NB_TH;
uint8_t tdd_period = mac->phy_config.config_req.tdd_table.tdd_period_in_slots;
uint8_t num_UL_slots = mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots +
(mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0);
uint8_t first_tx_slot = tdd_period - num_UL_slots;
if (slot_tx_usrp%tdd_period==first_tx_slot)
flags=2;
else if (slot_tx_usrp%tdd_period==first_tx_slot+num_UL_slots-1)
flags = 3;
else if (slot_tx_usrp%tdd_period>first_tx_slot)
flags = 1;
if (flags || IS_SOFTMODEM_RFSIM)
AssertFatal( writeBlockSize ==
UE->rfdevice.trx_write_func(&UE->rfdevice,
writeTimestamp,
txp,
writeBlockSize,
UE->frame_parms.nb_antennas_tx,
1),"");
writeTimestamp,
txp,
writeBlockSize,
UE->frame_parms.nb_antennas_tx,
flags),"");
for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
memset(txp[i], 0, writeBlockSize);
......@@ -780,7 +730,7 @@ void *UE_thread(void *arg) {
msgToPush->key=slot_nr;
pushTpool(&(get_nrUE_params()->Tpool), msgToPush);
if ( IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR")
if (IS_SOFTMODEM_RFSIM) { //getenv("RFSIMULATOR")
// FixMe: Wait previous thread is done, because race conditions seems too bad
// in case of actual RF board, the overlap between threads mitigate the issue
// We must receive one message, that proves the slot processing is done
......
......@@ -298,7 +298,6 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
tx_gain[0][CC_id] = tx_gain[0][0];
// Set UE variables
UE->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
UE->tx_total_gain_dB = (int)tx_gain[CC_id][0];
UE->tx_power_max_dBm = tx_max_power[CC_id];
......@@ -576,22 +575,15 @@ int main( int argc, char **argv ) {
init_NR_UE_threads(1);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
printf("UE threads created by %ld\n", gettid());
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
protocol_ctxt_t ctxt_pP = {0};
ctxt_pP.enb_flag = ENB_FLAG_NO;
ctxt_pP.rnti = 0x1234;
RC.nrrrc = (gNB_RRC_INST **)malloc(1*sizeof(gNB_RRC_INST *));
RC.nrrrc[0] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST));
RC.nrrrc[0]->node_type = ngran_gNB;
rrc_ue_generate_RRCSetupRequest(&ctxt_pP, 0);
if (create_tasks_nrue(1) < 0) {
printf("cannot create ITTI tasks\n");
exit(-1); // need a softer mode
}
// Sleep a while before checking all parameters have been used
// Some are used directly in external threads, asynchronously
sleep(20);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
while(true)
sleep(3600);
......
......@@ -50,15 +50,15 @@
{"ue-rxgain", CONFIG_HLP_UERXG, 0, dblptr:&(rx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, dblptr:&rx_gain_off, defdblval:0, TYPE_DOUBLE, 0}, \
{"ue-txgain", CONFIG_HLP_UETXG, 0, dblptr:&(tx_gain[0][0]), defdblval:0, TYPE_DOUBLE, 0}, \
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&(fp->nb_antennas_rx), defuintval:1, TYPE_UINT8, 0}, \
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&(fp->nb_antennas_tx), defuintval:1, TYPE_UINT8, 0}, \
{"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&(UE->UE_scan_carrier), defintval:0, TYPE_INT, 0}, \
{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&(UE->UE_fo_compensation), defintval:0, TYPE_INT, 0}, \
{"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \
{"r" , CONFIG_HLP_PRB, 0, iptr:&(fp->N_RB_DL), defintval:25, TYPE_UINT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \
{"A" , CONFIG_HLP_TADV, 0, iptr:&(UE->timing_advance), defintval:0, TYPE_INT, 0}, \
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, u8ptr:&(fp->threequarter_fs), defintval:0, TYPE_UINT8, 0}, \
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
{"T" , CONFIG_HLP_TDD, PARAMFLAG_BOOL, iptr:&tddflag, defintval:0, TYPE_INT, 0}, \
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, iptr:&(UE->no_timing_correction), defintval:0, TYPE_INT, 0}, \
}
......
......@@ -39,11 +39,14 @@
#include "executables/thread-common.h"
#include "common/utils/LOG/log.h"
#include "softmodem-common.h"
#include "nfapi/oai_integration/vendor_ext.h"
static softmodem_params_t softmodem_params;
char *parallel_config=NULL;
char *worker_config=NULL;
uint8_t nfapi_mode=0;
static mapping softmodem_funcs[] = MAPPING_SOFTMODEM_FUNCTIONS;
static struct timespec start;
......@@ -143,6 +146,7 @@ void get_common_options(uint32_t execmask) {
if(parallel_config != NULL) set_parallel_conf(parallel_config);
if(worker_config != NULL) set_worker_conf(worker_config);
nfapi_setmode(nfapi_mode);
}
void softmodem_printresources(int sig, telnet_printfunc_t pf) {
struct rusage usage;
......
......@@ -91,6 +91,7 @@ extern "C"
#define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n"
#define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n"
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters common to eNodeB and UE */
......@@ -112,6 +113,7 @@ extern "C"
#define SEND_DMRSSYNC softmodem_params.send_dmrs_sync
#define USIM_TEST softmodem_params.usim_test
#define USE_256QAM_TABLE softmodem_params.use_256qam_table
#define NFAPI softmodem_params.nfapi
#define DEFAULT_RFCONFIG_FILE "/usr/local/etc/syriq/ue.band7.tm1.PRB100.NR40.dat";
......@@ -142,6 +144,7 @@ extern "C"
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
{"use-256qam-table", CONFIG_HLP_256QAM, PARAMFLAG_BOOL, iptr:&USE_256QAM_TABLE, defintval:0, TYPE_INT, 0}, \
{"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \
}
......@@ -229,6 +232,7 @@ typedef struct {
int hw_timing_advance;
uint32_t send_dmrs_sync;
int use_256qam_table;
uint8_t nfapi;
} softmodem_params_t;
extern uint64_t get_softmodem_optmask(void);
......@@ -240,6 +244,7 @@ extern char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr);
extern void set_softmodem_sighandler(void);
extern uint64_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
extern uint8_t nfapi_mode;
#ifdef __cplusplus
}
#endif
......
# Procedure to run nFAPI in 5G NR
## Conributed by 5G Testbed IISC
### Developers: Sudhakar B,Mahesh K,Gokul S,Aniq U.R
## Procedure to Build gNB and UE
The regular commands to build gNB and UE can be used
```
sudo ./build_oai --gNB --UE
```
## Procedure to run NR nFAPI using RF-Simulator
### VNF command
```
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test
```
### PNF command
```
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --rfsim --phy-test --rfsimulator.serveraddr server
```
### UE command
```
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path . -d
```
## Procedure to run NR nFAPI using Hardware
Will be updated as we have not yet currently tested on hardware
## Notes
* In order to acheive the synchronization between VNF and PNF and receive the P7 messages within the timing window the order in which we should run the modules on different terminals is UE->VNF->PNF
* Currently only downlink is functional and working as we are still working on uplink functionality
This diff is collapsed.
......@@ -23,5 +23,8 @@
#define NFAPI_PNF_H__
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind);
void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
void oai_subframe_ind(uint16_t sfn, uint16_t sf);
void oai_slot_ind(uint16_t sfn, uint16_t slot);
#endif
This diff is collapsed.
......@@ -23,5 +23,5 @@
#define NFAPI_VNF_H__
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port);
void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port);
#endif
......@@ -1019,6 +1019,7 @@ typedef struct
typedef struct
{
uint8_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4
uint8_t tdd_period_in_slots;
fapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list;
} fapi_nr_tdd_table_t;
......
......@@ -120,6 +120,17 @@ typedef struct {
} nfapi_tl_t;
#define NFAPI_TAG_LENGTH_PACKED_LEN 4
// Convenience methods to convert between SFN/SLOT formats
#define NFAPI_SFNSLOT2DEC(_sfn,_slot) ( _sfn*20 + _slot ) // total count of slots
#define NFAPI_SFNSLOTDEC2SFNSLOT(_sfnslot_dec) ((((_sfnslot_dec) / 20) << 4) | (((_sfnslot_dec) - (((_sfnslot_dec) / 20) * 10)) & 0x3F))
#define NFAPI_SFNSLOT2SFN(_sfnslot) ((_sfnslot) >> 6)
#define NFAPI_SFNSLOT2SLOT(_sfnslot) ((_sfnslot) & 0x3F)
#define NFAPI_SFNSLOTDEC2SFN(_sfnslot_dec) ((_sfnslot_dec) / 20)
#define NFAPI_SFNSLOTDEC2SLOT(_sfnslot_dec) ((_sfnslot_dec) % 20)
#define NFAPI_MAX_SFNSLOTDEC 1024*20 // 20 is for numerology 1
// Convenience methods to convert between SFN/SFN formats
#define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF))
#define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF))
......@@ -176,7 +187,6 @@ typedef enum {
NFAPI_DL_NODE_SYNC,
NFAPI_TIMING_INFO,
NFAPI_RSSI_REQUEST = 0x0200,
NFAPI_RSSI_RESPONSE,
NFAPI_RSSI_INDICATION,
......@@ -587,6 +597,26 @@ typedef struct {
#define NFAPI_PNF_PHY_RF_TAG 0x1003
// Generic strucutre for single tlv value.
typedef struct {
nfapi_tl_t tl;
int32_t value;
} nfapi_int32_tlv_t;
typedef struct {
nfapi_tl_t tl;
uint32_t value;
} nfapi_uint32_tlv_t;
typedef struct {
nfapi_tl_t tl;
int64_t value;
} nfapi_int64_tlv_t;
typedef struct {
nfapi_tl_t tl;
uint64_t value;
} nfapi_uint64_tlv_t;
typedef struct {
nfapi_tl_t tl;
uint16_t value;
......@@ -1106,6 +1136,7 @@ typedef struct {
typedef struct {
nfapi_p4_p5_message_header_t header;
uint8_t num_tlvs;
nfapi_pnf_phy_rf_config_t pnf_phy_rf_config;
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_pnf_config_request_t;
......@@ -2466,7 +2497,7 @@ typedef struct {
typedef struct {
nfapi_p7_message_header_t header;
uint32_t t1;
int32_t delta_sfn_sf;
int32_t delta_sfn_sf;
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_dl_node_sync_t;
......@@ -2481,22 +2512,50 @@ typedef struct {
typedef struct {
nfapi_p7_message_header_t header;
uint32_t last_sfn_sf;
uint32_t time_since_last_timing_info;
uint32_t dl_config_jitter;
uint32_t tx_request_jitter;
uint32_t ul_config_jitter;
uint32_t hi_dci0_jitter;
int32_t dl_config_latest_delay;
int32_t tx_request_latest_delay;
int32_t ul_config_latest_delay;
int32_t hi_dci0_latest_delay;
int32_t dl_config_earliest_arrival;
int32_t tx_request_earliest_arrival;
int32_t ul_config_earliest_arrival;
int32_t hi_dci0_earliest_arrival;
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_timing_info_t;
typedef struct {
nfapi_p7_message_header_t header;
uint32_t last_sfn;
uint32_t last_slot;
uint32_t time_since_last_timing_info;
uint32_t dl_tti_jitter;
uint32_t tx_data_request_jitter;
uint32_t ul_tti_jitter;
uint32_t ul_dci_jitter;
int32_t dl_tti_latest_delay;
int32_t tx_data_request_latest_delay;
int32_t ul_tti_latest_delay;
int32_t ul_dci_latest_delay;
int32_t dl_tti_earliest_arrival;
int32_t tx_data_request_earliest_arrival;
int32_t ul_tti_earliest_arrival;
int32_t ul_dci_earliest_arrival;
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_nr_timing_info_t;
typedef struct {
nfapi_tl_t tl;
uint32_t handle;
......@@ -3653,6 +3712,50 @@ typedef struct {
nfapi_vendor_extension_tlv_t vendor_extension;
} nfapi_nmm_stop_response_t;
typedef struct
{
// TODO: see if this needs to be uncommented
// These TLVs are used to setup the transport connection between VNF and PNF
nfapi_ipv4_address_t p7_vnf_address_ipv4;
nfapi_ipv6_address_t p7_vnf_address_ipv6;
nfapi_uint16_tlv_t p7_vnf_port;
nfapi_ipv4_address_t p7_pnf_address_ipv4;
nfapi_ipv6_address_t p7_pnf_address_ipv6;
nfapi_uint16_tlv_t p7_pnf_port;
nfapi_uint8_tlv_t timing_window; //Value: 0 → 30,000 microseconds
nfapi_uint8_tlv_t timing_info_mode;
nfapi_uint8_tlv_t timing_info_period;
nfapi_uint32_tlv_t dl_tti_timing_offset;
nfapi_uint32_tlv_t ul_tti_timing_offset;
nfapi_uint32_tlv_t ul_dci_timing_offset;
nfapi_uint32_tlv_t tx_data_timing_offset;
// These TLVs are used to setup the transport connection between VNF and PNF
/*
nfapi_uint8_tlv_t dl_ue_per_sf;
nfapi_uint8_tlv_t ul_ue_per_sf;
// These TLVs are used by PNF to report its RF capabilities to the VNF software
nfapi_rf_bands_t rf_bands;
*/
// These TLVs are used by the VNF to configure the synchronization with the PNF.
// These TLVs are used by the VNF to configure the RF in the PNF
//nfapi_uint16_tlv_t max_transmit_power;
//nfapi_uint32_tlv_t nrarfcn;
// nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands;
// nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands;
// nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands;
// nfapi_uint8_tlv_t nmm_uplink_rssi_supported;
} nfapi_nr_nfapi_t;
//
// Configuration options for the encode decode functions
//
......@@ -3864,6 +3967,7 @@ int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn
*
*/
int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
int nfapi_nr_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
/*! \brief Decodes an NFAPI P5 message header
* \param pMessageBuf A pointer to an encoded P5 message header
......@@ -3887,6 +3991,7 @@ int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo
*
* The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf
*/
int nfapi_nr_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
/*! \brief Encodes an NFAPI P7 message to a buffer
......@@ -3900,6 +4005,7 @@ int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUn
*
*/
int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config);
int nfapi_nr_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config);
/*! \brief Decodes an NFAPI P7 message header
* \param pMessageBuf A pointer to an encoded P7 message header
......@@ -3925,6 +4031,7 @@ int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, vo
* The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf
*/
int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
int nfapi_nr_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
/*! \brief Calculates the checksum of a message
*
......
......@@ -10,7 +10,7 @@
#define _NFAPI_NR_INTERFACE_H_
#include "nfapi_interface.h"
#include <nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h>
#include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h"
#define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5
#define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64
......@@ -22,62 +22,32 @@
// nFAPI enums
//These TLVs are used exclusively by nFAPI
typedef struct
{
// These TLVs are used to setup the transport connection between VNF and PNF
// nfapi_ipv4_address_t p7_vnf_address_ipv4;
// nfapi_ipv6_address_t p7_vnf_address_ipv6;
// nfapi_uint16_tlv_t p7_vnf_port;
// nfapi_ipv4_address_t p7_pnf_address_ipv4;
// nfapi_ipv6_address_t p7_pnf_address_ipv6;
// nfapi_uint16_tlv_t p7_pnf_port;
// // These TLVs are used to setup the transport connection between VNF and PNF
// nfapi_uint8_tlv_t dl_ue_per_sf;
// nfapi_uint8_tlv_t ul_ue_per_sf;
// These TLVs are used by PNF to report its RF capabilities to the VNF software
nfapi_rf_bands_t rf_bands;
// These TLVs are used by the VNF to configure the synchronization with the PNF.
// nfapi_uint8_tlv_t timing_window;
// nfapi_uint8_tlv_t timing_info_mode;
// nfapi_uint8_tlv_t timing_info_period;
// These TLVs are used by the VNF to configure the RF in the PNF
// nfapi_uint16_tlv_t max_transmit_power;
nfapi_uint32_tlv_t nrarfcn;
// nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands;
// nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands;
// nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands;
// nfapi_uint8_tlv_t nmm_uplink_rssi_supported;
} nfapi_nr_nfapi_t;
#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x5100
#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x5101
#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x5102
#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x5103
#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x5104
#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x5105
#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100
#define NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101
#define NFAPI_NR_NFAPI_P7_VNF_PORT_TAG 0x0102
#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103
#define NFAPI_NR_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104
#define NFAPI_NR_NFAPI_P7_PNF_PORT_TAG 0x0105
#define NFAPI_NR_NFAPI_DL_TTI_TIMING_OFFSET 0x0106
#define NFAPI_NR_NFAPI_UL_TTI_TIMING_OFFSET 0x0107
#define NFAPI_NR_NFAPI_UL_DCI_TIMING_OFFSET 0x0108
#define NFAPI_NR_NFAPI_TX_DATA_TIMING_OFFSET 0x0109
#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x011E
#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x011F
#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
/*
#define NFAPI_NR_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x510A
#define NFAPI_NR_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x510B
#define NFAPI_NR_NFAPI_RF_BANDS_TAG 0x5114
#define NFAPI_NR_NFAPI_TIMING_WINDOW_TAG 0x511E
#define NFAPI_NR_NFAPI_TIMING_INFO_MODE_TAG 0x511F
#define NFAPI_NR_NFAPI_TIMING_INFO_PERIOD_TAG 0x5120
#define NFAPI_NR_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x5128
#define NFAPI_NR_NFAPI_NRARFCN_TAG 0x5129
#define NFAPI_NR_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x5130
#define NFAPI_NR_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x5131
#define NFAPI_NR_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x5132
#define NFAPI_NR_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x5133
*/
// P5 Message Structures
typedef struct {
......@@ -323,7 +293,7 @@ typedef enum {
typedef enum {
NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED=0,
NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED
NFAPI_NR_CCE_REG_MAPPING_NON_INTERLEAVED=1
} nfapi_nr_cce_reg_mapping_type_e;
typedef enum {
......
......@@ -712,7 +712,7 @@ int unpack_tlv_list(unpack_tlv_t unpack_fns[], uint16_t size, uint8_t **ppReadPa
for(idx = 0; idx < size; ++idx)
{
if(unpack_fns[idx].tag == generic_tl.tag)
if(unpack_fns[idx].tag == generic_tl.tag) // match the extracted tag value with all the tags in unpack_fn list
{
tagMatch = 1;
nfapi_tl_t* tl = (nfapi_tl_t*)(unpack_fns[idx].tlv);
......
This diff is collapsed.
This diff is collapsed.
......@@ -38,7 +38,9 @@ typedef struct {
int pnf_connect(pnf_t *pnf);
int pnf_message_pump(pnf_t *pnf);
int pnf_nr_message_pump(pnf_t *pnf);
int pnf_nr_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
int pnf_pack_and_send_p5_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
int pnf_pack_and_send_p4_message(pnf_t* pnf, nfapi_p4_p5_message_header_t* msg, uint32_t msg_len);
int pnf_send_message(pnf_t* pnf, uint8_t* msg, uint32_t msg_len, uint16_t stream_id);
......
......@@ -29,15 +29,37 @@
typedef struct {
uint16_t dl_conf_ontime;
uint16_t dl_tti_ontime;
uint16_t dl_conf_late;
uint16_t dl_tti_late;
uint16_t ul_conf_ontime;
uint16_t ul_tti_ontime;
uint16_t ul_conf_late;
uint16_t ul_tti_late;
uint16_t hi_dci0_ontime;
uint16_t hi_dci0_late;
uint16_t ul_dci_ontime;
uint16_t ul_dci_late;
uint16_t tx_ontime;
uint16_t tx_late;
uint16_t tx_data_ontime;
uint16_t tx_data_late;
} pnf_p7_stats_t;
typedef struct { // TODO: replace with the stats
uint16_t dl_tti_ontime;
uint16_t dl_tti_late;
uint16_t ul_tti_ontime;
uint16_t ul_tti_late;
uint16_t ul_dci_ontime;
uint16_t ul_dci_late;
uint16_t tx_data_ontime;
uint16_t tx_data_late;
} pnf_p7_nr_stats_t;
typedef struct {
uint8_t* buffer;
uint16_t length;
......@@ -82,7 +104,7 @@ typedef struct {
pthread_mutex_t pack_mutex; // should we allow the client to specifiy
nfapi_pnf_p7_subframe_buffer_t subframe_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/];
nfapi_pnf_p7_slot_buffer_t slot_buffer[30/*NFAPI_MAX_TIMING_WINDOW_SIZE*/];
uint32_t sequence_number;
uint16_t max_num_segments;
......@@ -94,6 +116,12 @@ typedef struct {
uint16_t sfn_sf;
uint32_t sf_start_time_hr;
int32_t sfn_sf_shift;
uint16_t sfn;
uint16_t slot;
uint16_t sfn_slot;
uint32_t slot_start_time_hr;
int32_t slot_shift;
uint8_t timing_info_period_counter;
uint8_t timing_info_aperiodic_send; // 0:false 1:true
......@@ -104,18 +132,26 @@ typedef struct {
uint32_t ul_config_jitter;
uint32_t hi_dci0_jitter;
uint32_t tx_jitter;
//P7 NR
uint32_t dl_tti_jitter;
uint32_t ul_tti_jitter;
uint32_t ul_dci_jitter;
uint32_t tx_data_jitter;
uint32_t tick;
pnf_p7_stats_t stats;
pnf_p7_nr_stats_t nr_stats;
} pnf_p7_t;
int pnf_p7_message_pump(pnf_p7_t* pnf_p7);
int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7);
int pnf_p7_pack_and_send_p7_message(pnf_p7_t* pnf_p7, nfapi_p7_message_header_t* msg, uint32_t msg_len);
int pnf_p7_send_message(pnf_p7_t* pnf_p7, uint8_t* msg, uint32_t msg_len);
int pnf_p7_slot_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot);
int pnf_p7_subframe_ind(pnf_p7_t* config, uint16_t phy_id, uint16_t sfn_sf);
pnf_p7_rx_message_t* pnf_p7_rx_reassembly_queue_add_segment(pnf_p7_t* pnf_p7, pnf_p7_rx_reassembly_queue_t* queue, uint32_t rx_hr_time, uint16_t sequence_number, uint16_t segment_number, uint8_t m, uint8_t* data, uint16_t data_len);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -31,7 +31,7 @@ nfapi_pnf_p7_config_t* nfapi_pnf_p7_config_create()
_this->_public.segment_size = 1400;
_this->max_num_segments = 8;
_this->_public.subframe_buffer_size = 8;
_this->_public.subframe_buffer_size = 8;// TODO: Initialize the slot_buffer size
_this->_public.timing_info_mode_periodic = 1;
_this->_public.timing_info_period = 32;
_this->_public.timing_info_mode_aperiodic = 1;
......@@ -76,6 +76,26 @@ int nfapi_pnf_p7_start(nfapi_pnf_p7_config_t* config)
return 0;
}
int nfapi_nr_pnf_p7_start(nfapi_pnf_p7_config_t* config)
{
// Verify that config is not null
if(config == 0)
return -1;
// Make sure to set the defined trace function before using NFAPI_TRACE
if(config->trace)
nfapi_trace_g = config->trace;
pnf_p7_t* _this = (pnf_p7_t*)(config);
NFAPI_TRACE(NFAPI_TRACE_INFO, "%s\n", __FUNCTION__);
pnf_nr_p7_message_pump(_this);
return 0;
}
int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config)
{
// Verify that config is not null
......@@ -88,6 +108,16 @@ int nfapi_pnf_p7_stop(nfapi_pnf_p7_config_t* config)
return 0;
}
int nfapi_pnf_p7_slot_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn, uint16_t slot)
{
// Verify that config is not null
if(config == 0)
return -1;
pnf_p7_t* _this = (pnf_p7_t*)(config);
return pnf_p7_slot_ind(_this, phy_id, sfn, slot);
}
int nfapi_pnf_p7_subframe_ind(nfapi_pnf_p7_config_t* config, uint16_t phy_id, uint16_t sfn_sf)
{
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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