Merge branch 'integration_2023_w05' into 'develop'
integration_2023_w05 See merge request oai/openairinterface5g!1936 * !1897 NR improvements for scheduling with DCI 1_0 * !1899 Fix buffer overflow and memory alignment at the UE * !1916 Remove legacy 4G RLC * !1920 bugfix: fix sdap * !1923 fix(ci): fixes to run on caracal after RHEL9 migration * !1931 set max UEs to be scheduled by MAC * !1573 FAPI: correct port numbers, clean up some comments * !1765 Improve USRP GPIO handling * !1868 Change the nFAPI command line parameter of nr-softmodem (--nfapi) to expect string values instead of integer values * !1930 improving MIMO section on runmodem file * !1934 Make rftest compile
This commit is contained in:
+2
-68
@@ -155,7 +155,6 @@ set (NFAPI_USER_DIR ${OPENAIR_DIR}/nfapi/oai_integration)
|
||||
set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1)
|
||||
set (OPENAIR2_DIR ${OPENAIR_DIR}/openair2)
|
||||
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
|
||||
set (OPENAIR_TARGETS ${OPENAIR_DIR}/targets)
|
||||
set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3)
|
||||
set (OPENAIR_CMAKE ${OPENAIR_DIR}/cmake_targets)
|
||||
set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
|
||||
@@ -342,7 +341,6 @@ add_boolean_option(DISABLE_XER_PRINT False "print XER Format")
|
||||
add_boolean_option(XER_PRINT False "print XER Format")
|
||||
add_boolean_option(DEBUG_PDCP_PAYLOAD False "print PDCP PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(DEBUG_MAC_INTERFACE False "print MAC-RLC PDU exchange to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(TRACE_RLC_PAYLOAD False "print RLC PDU to stdout") # if true, make sure that global and PDCP log levels are trace
|
||||
add_boolean_option(PRINT_STATS False "This adds the possibility to see the status")
|
||||
add_boolean_option(T_TRACER True "Activate the T tracer, a debugging/monitoring framework" )
|
||||
add_boolean_option(UE_AUTOTEST_TRACE False "Activate UE autotest specific logs")
|
||||
@@ -720,31 +718,6 @@ add_boolean_option(NAS_UE True "NAS UE INSTANCE (<> NAS_MME)")
|
||||
##########################
|
||||
add_boolean_option(JUMBO_FRAME True "ENABLE LARGE SDU in ACCESS STRATUM (larger than common MTU)")
|
||||
|
||||
##########################
|
||||
# RLC LAYER OPTIONS
|
||||
##########################
|
||||
add_boolean_option(TRACE_RLC_PAYLOAD False "Fatal assert in this case")
|
||||
add_boolean_option(RLC_STOP_ON_LOST_PDU False "Fatal assert in this case")
|
||||
|
||||
add_boolean_option(TRACE_RLC_MUTEX True "TRACE for RLC, possible problem in thread scheduling")
|
||||
add_boolean_option(TRACE_RLC_AM_BO False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_FREE_SDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_HOLE False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_PDU False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_RESEGMENT False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_RX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_TX False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_TX_STATUS False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_AM_STATUS_CREATION False "TRACE for RLC AM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
|
||||
add_boolean_option(STOP_ON_IP_TRAFFIC_OVERLOAD False "")
|
||||
add_boolean_option(TRACE_RLC_UM_DAR False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_UM_DISPLAY_ASCII_DATA False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_UM_PDU False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_UM_RX False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_UM_SEGMENT False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGED IN A MORE GENERAL FLAG")
|
||||
|
||||
|
||||
##########################
|
||||
# PDCP LAYER OPTIONS
|
||||
@@ -804,9 +777,6 @@ include_directories("${OPENAIR2_DIR}/ENB_APP")
|
||||
include_directories("${OPENAIR2_DIR}/GNB_APP")
|
||||
include_directories("${OPENAIR2_DIR}/MCE_APP")
|
||||
include_directories("${OPENAIR2_DIR}/LAYER2/RLC")
|
||||
include_directories("${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0")
|
||||
include_directories("${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0")
|
||||
include_directories("${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0")
|
||||
include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0")
|
||||
include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES")
|
||||
include_directories("${OPENAIR2_DIR}/RRC/LTE")
|
||||
@@ -831,7 +801,6 @@ include_directories("${OPENAIR2_DIR}/F1AP")
|
||||
include_directories("${OPENAIR3_DIR}/ocp-gtpu")
|
||||
include_directories("${OPENAIR3_DIR}/M3AP")
|
||||
include_directories("${OPENAIR3_DIR}/MME_APP")
|
||||
include_directories("${OPENAIR_DIR}/targets/COMMON")
|
||||
include_directories("${OPENAIR_DIR}/radio/COMMON")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/PHY")
|
||||
include_directories("${OPENAIR2_DIR}/ENB_APP/CONTROL_MODULES/MAC")
|
||||
@@ -864,8 +833,6 @@ add_library(HASHTABLE
|
||||
include_directories(${OPENAIR_DIR}/common/utils/hashtable)
|
||||
|
||||
add_library(UTIL
|
||||
${OPENAIR2_DIR}/UTIL/LISTS/list.c
|
||||
${OPENAIR2_DIR}/UTIL/LISTS/list2.c
|
||||
${OPENAIR_DIR}/common/utils/LOG/log.c
|
||||
${OPENAIR_DIR}/common/utils/LOG/vcd_signal_dumper.c
|
||||
${OPENAIR2_DIR}/UTIL/MATH/oml.c
|
||||
@@ -1409,45 +1376,11 @@ set(NR_UE_MAC_DIR ${OPENAIR2_DIR}/LAYER2/NR_MAC_UE)
|
||||
set(PHY_INTERFACE_DIR ${OPENAIR2_DIR}/PHY_INTERFACE)
|
||||
set(NR_PHY_INTERFACE_DIR ${OPENAIR2_DIR}/NR_PHY_INTERFACE)
|
||||
set(NR_UE_PHY_INTERFACE_DIR ${OPENAIR2_DIR}/NR_UE_PHY_INTERFACE)
|
||||
set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC)
|
||||
set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0)
|
||||
set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0)
|
||||
set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0)
|
||||
set(RRC_DIR ${OPENAIR2_DIR}/RRC/LTE)
|
||||
set(NR_RRC_DIR ${OPENAIR2_DIR}/RRC/NR)
|
||||
set(NR_UE_RRC_DIR ${OPENAIR2_DIR}/RRC/NR_UE)
|
||||
set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
|
||||
|
||||
set(RLC_V1
|
||||
${RLC_AM_DIR}/rlc_am.c
|
||||
${RLC_AM_DIR}/rlc_am_init.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_reordering.c
|
||||
${RLC_AM_DIR}/rlc_am_timer_status_prohibit.c
|
||||
${RLC_AM_DIR}/rlc_am_segment.c
|
||||
${RLC_AM_DIR}/rlc_am_segments_holes.c
|
||||
${RLC_AM_DIR}/rlc_am_in_sdu.c
|
||||
${RLC_AM_DIR}/rlc_am_receiver.c
|
||||
${RLC_AM_DIR}/rlc_am_retransmit.c
|
||||
${RLC_AM_DIR}/rlc_am_windows.c
|
||||
${RLC_AM_DIR}/rlc_am_rx_list.c
|
||||
${RLC_AM_DIR}/rlc_am_reassembly.c
|
||||
${RLC_AM_DIR}/rlc_am_status_report.c
|
||||
${RLC_TM_DIR}/rlc_tm.c
|
||||
${RLC_TM_DIR}/rlc_tm_init.c
|
||||
${RLC_UM_DIR}/rlc_um.c
|
||||
${RLC_UM_DIR}/rlc_um_fsm.c
|
||||
${RLC_UM_DIR}/rlc_um_control_primitives.c
|
||||
${RLC_UM_DIR}/rlc_um_segment.c
|
||||
${RLC_UM_DIR}/rlc_um_reassembly.c
|
||||
${RLC_UM_DIR}/rlc_um_receiver.c
|
||||
${RLC_UM_DIR}/rlc_um_dar.c
|
||||
${RLC_DIR}/rlc_mac.c
|
||||
${RLC_DIR}/rlc.c
|
||||
${RLC_DIR}/rlc_rrc.c
|
||||
${RLC_DIR}/rlc_mpls.c
|
||||
)
|
||||
|
||||
set(RLC_V2
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_oai_api.c
|
||||
${OPENAIR2_DIR}/LAYER2/rlc_v2/asn1_utils.c
|
||||
@@ -2532,7 +2465,8 @@ add_executable(rftest
|
||||
${OPENAIR_DIR}/executables/softmodem-common.c
|
||||
${SHLIB_LOADER_SOURCES}
|
||||
)
|
||||
target_link_libraries(rftest minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m forms ${T_LIB} )
|
||||
target_link_libraries(rftest PRIVATE minimal_lib CONFIG_LIB PHY_NR_COMMON UTIL pthread dl m forms ${T_LIB} )
|
||||
target_link_libraries(rftest PRIVATE asn1_lte_rrc asn1_nr_rrc)
|
||||
|
||||
add_executable(polartest
|
||||
${OPENAIR1_DIR}/PHY/CODING/TESTBENCH/polartest.c
|
||||
|
||||
@@ -3179,7 +3179,7 @@ class OaiCiTest():
|
||||
result = re.search('warning: discard PDU, sn out of window', str(line))
|
||||
if result is not None:
|
||||
nbPduDiscard += 1
|
||||
result = re.search('--nfapi 5 --node-number 2 --sa', str(line))
|
||||
result = re.search('--nfapi STANDALONE_PNF --node-number 2 --sa', str(line))
|
||||
if result is not None:
|
||||
frequency_found = True
|
||||
result = re.search('Exiting OAI softmodem', str(line))
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<rt_stats_cfg>datalog_rt_stats.default.yaml</rt_stats_cfg>
|
||||
<air_interface>NR</air_interface>
|
||||
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
|
||||
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0 --membind=netdev:enp94s0f0</cmd_prefix>
|
||||
<cmd_prefix>numactl --cpunodebind=netdev:enp94s0f0np0 --membind=netdev:enp94s0f0np0</cmd_prefix>
|
||||
</testCase>
|
||||
|
||||
<testCase id="000001">
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<mode>TesteNB</mode>
|
||||
<class>Build_eNB</class>
|
||||
<desc>Build gNB (USRP)</desc>
|
||||
<Build_eNB_args>--gNB -w USRP --ninja --cmake-opt -DBoost_INCLUDE_DIR=/usr/include/boost169 --cmake-opt -DCUDA_HOST_COMPILER=/opt/rh/devtoolset-7/root/usr/bin/gcc -c -P</Build_eNB_args>
|
||||
<Build_eNB_args>--gNB -w USRP --ninja -c -P</Build_eNB_args>
|
||||
<forced_workspace_cleanup>True</forced_workspace_cleanup>
|
||||
</testCase>
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ services:
|
||||
LOCAL_S_IF_NAME: 'lo:'
|
||||
REMOTE_S_ADDRESS: 127.0.0.1
|
||||
LOCAL_S_ADDRESS: 127.0.0.2
|
||||
USE_ADDITIONAL_OPTIONS: --sa --nfapi 2 --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor
|
||||
USE_ADDITIONAL_OPTIONS: --sa --nfapi VNF --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor
|
||||
depends_on:
|
||||
- oai-spgwu
|
||||
- oai-amf
|
||||
@@ -295,7 +295,7 @@ services:
|
||||
NR_UE_NFAPI_IF_NAME: eno1
|
||||
GNB_IP_ADDRESS: 127.0.0.1
|
||||
NR_UE_IP_ADDRESS: 127.0.0.1
|
||||
USE_ADDITIONAL_OPTIONS: --nokrnmod 1 --nfapi 5 --node-number 2 --sa --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor
|
||||
USE_ADDITIONAL_OPTIONS: --nokrnmod 1 --nfapi STANDALONE_PNF --node-number 2 --sa --emulate-l1 --log_config.global_log_options level,time,thread_id,nocolor
|
||||
volumes:
|
||||
- ../../../openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results:/opt/oai-nr-ue/openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results
|
||||
depends_on:
|
||||
|
||||
@@ -122,6 +122,9 @@ check_supported_distribution() {
|
||||
"rhel8.6") return 0 ;;
|
||||
"rhel8.7") return 0 ;;
|
||||
"rhel9.0") return 0 ;;
|
||||
"rhel9.1") return 0 ;;
|
||||
"rhel9.2") return 0 ;;
|
||||
"rhel9.3") return 0 ;;
|
||||
"centos7") return 0 ;;
|
||||
"centos8") return 0 ;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
/*! \file var_array.c
|
||||
* \brief Very primitive variable length array ds. Here for compatibility
|
||||
* reasons, should be replaced with a more capable data structure.
|
||||
* @ingroup util
|
||||
*/
|
||||
|
||||
#ifndef VAR_ARRAY_H_
|
||||
#define VAR_ARRAY_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "common/utils/assertions.h"
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
size_t mallocedSize;
|
||||
size_t atomSize;
|
||||
size_t increment;
|
||||
} varArray_t;
|
||||
|
||||
static inline varArray_t *initVarArray(size_t increment, size_t atomSize)
|
||||
{
|
||||
varArray_t *tmp = malloc(sizeof(*tmp) + increment * atomSize);
|
||||
tmp->size = 0;
|
||||
tmp->atomSize = atomSize;
|
||||
tmp->mallocedSize = increment;
|
||||
tmp->increment = increment;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void *dataArray(varArray_t *input)
|
||||
{
|
||||
return input + 1;
|
||||
}
|
||||
|
||||
static inline void appendVarArray(varArray_t **inputPtr, void *data)
|
||||
{
|
||||
varArray_t *input = *inputPtr;
|
||||
if (input->size >= input->mallocedSize) {
|
||||
input->mallocedSize += input->increment;
|
||||
*inputPtr = realloc(input, sizeof(varArray_t) + input->mallocedSize * input->atomSize);
|
||||
AssertFatal(*inputPtr, "no memory left");
|
||||
input = *inputPtr;
|
||||
}
|
||||
memcpy((uint8_t *)(input + 1) + input->atomSize * input->size++, data, input->atomSize);
|
||||
}
|
||||
|
||||
static inline void freeVarArray(varArray_t *input)
|
||||
{
|
||||
free(input);
|
||||
}
|
||||
|
||||
#endif /* VAR_ARRAY_H_ */
|
||||
+10
-2
@@ -220,6 +220,10 @@ UE on machine 2:
|
||||
|
||||
# MIMO configuration
|
||||
|
||||
In order to enable DL-MIMO in OAI 5G softmodem, the prerequisite is to have `do_CSIRS = 1` in the configuration file. This allows the gNB to schedule CSI reference signal and to acquire from the UE CSI measurements to be able to schedule DLSCH with MIMO.
|
||||
|
||||
The following step is to set the number of PDSCH logical antenna ports. These needs to be larger or equal to the maximum number of MIMO layers requested (for 2-layer MIMO it is necessary to have at least two logical antenna ports).
|
||||
|
||||
<table style="border-collapse: collapse; border: none;">
|
||||
<tr style="border-collapse: collapse; border: none;">
|
||||
<td style="border-collapse: collapse; border: none;">
|
||||
@@ -231,9 +235,13 @@ UE on machine 2:
|
||||
|
||||
This image shows an example of gNB 5G MIMO logical antenna port configuration. It has to be noted that logical antenna ports might not directly correspond to physical antenna ports and each logical antenna port might consist of a sub-array of antennas.
|
||||
|
||||
The basic element is a dual-polarized antenna, therefore the minimal DL MIMO setup with two logical antenna ports would consist of two cross-polarized antenna elements. In a single panel configuration, as the one in the picture, this element can be repeated vertiacally and/or horizontally to form an equi-spaced 1D or 2D array. The values N1 and N2 represent the number of antenna ports in the two dimensions and the supported configurations are specified in Section 5.2.2.2.1 of TS 38.214.
|
||||
In 5G the basic element is a dual-polarized antenna, therefore the minimal DL MIMO setup with two logical antenna ports would consist of two cross-polarized antenna elements. In a single panel configuration, as the one in the picture, this element can be repeated vertically and/or horizontally to form an equi-spaced 1D or 2D array. The values N1 and N2 represent the number of antenna ports in the two dimensions and the supported configurations are specified in Section 5.2.2.2.1 of TS 38.214.
|
||||
|
||||
The DL logical antenna port configuration can be selected through configuration file. `pdsch_AntennaPorts_N1` can be used to set N1 parameter, `pdsch_AntennaPorts_N2` to set N2 and `pdsch_AntennaPorts_XP` to set the cross-polarization configuration (1 for single pol, 2 for cross-pol). To be noted that if XP is 1 but N1 and/or N2 are larger than 1, this would result in a non-standard configuration and the PMI selected would be the identity matrix regardless of CSI report. The default value for each of these parameters is 1.
|
||||
The DL logical antenna port configuration can be selected through configuration file. `pdsch_AntennaPorts_N1` can be used to set N1 parameter, `pdsch_AntennaPorts_N2` to set N2 and `pdsch_AntennaPorts_XP` to set the cross-polarization configuration (1 for single pol, 2 for cross-pol). To be noted that if XP is 1 but N1 and/or N2 are larger than 1, this would result in a non-standard configuration and the PMI selected would be the identity matrix regardless of CSI report. The default value for each of these parameters is 1. The total number of PDSCH logical antenna ports is the multiplication of those 3 parameters.
|
||||
|
||||
Finally the number of TX physical antenna in the RU part of the configuration file, `nb_tx`, should be equal or larger than the total number of PDSCH logical antenna ports.
|
||||
|
||||
[Example of configuration file with parameters for 2-layer MIMO](https://gitlab.eurecom.fr/oai/openairinterface5g/-/blob/develop/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.fr1.273PRB.2x2.usrpn300.conf)
|
||||
|
||||
# Additional links
|
||||
|
||||
|
||||
+4
-4
@@ -21,12 +21,12 @@ sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up
|
||||
|
||||
### VNF command
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi VNF --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
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi PNF --rfsim --phy-test --rfsimulator.serveraddr server
|
||||
|
||||
```
|
||||
### UE command
|
||||
@@ -38,12 +38,12 @@ sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --rfsim --phy-test --rrc_config_path
|
||||
|
||||
### VNF command
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi 2 --noS1 --phy-test
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/rcc.band78.tm1.106PRB.nfapi.conf --nfapi VNF --noS1 --phy-test
|
||||
|
||||
```
|
||||
### PNF command
|
||||
```
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi 1 --phy-test
|
||||
sudo ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/oaiL1.nfapi.usrpx300.conf --nfapi PNF --phy-test
|
||||
|
||||
```
|
||||
### UE command
|
||||
|
||||
@@ -742,7 +742,8 @@ void tx_rf(RU_t *ru,
|
||||
|
||||
if ((SF_type == SF_DL) ||
|
||||
(SF_type == SF_S) ) {
|
||||
int siglen=fp->samples_per_tti,flags=1;
|
||||
int siglen=fp->samples_per_tti;
|
||||
radio_tx_burst_flag_t flags = TX_BURST_MIDDLE;
|
||||
|
||||
if (SF_type == SF_S) {
|
||||
int txsymb = fp->dl_symbols_in_S_subframe+(ru->is_slave==0 ? 1 : 0);
|
||||
@@ -757,13 +758,13 @@ void tx_rf(RU_t *ru,
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
|
||||
+ (txsymb - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
|
||||
+ ru->end_of_burst_delay;
|
||||
flags=3; // end of burst
|
||||
flags = TX_BURST_END;
|
||||
}
|
||||
|
||||
if (fp->frame_type == TDD &&
|
||||
SF_type == SF_DL &&
|
||||
prevSF_type == SF_UL) {
|
||||
flags = 2; // start of burst
|
||||
flags = TX_BURST_START;
|
||||
sf_extension = ru->sf_extension;
|
||||
}
|
||||
|
||||
@@ -781,24 +782,24 @@ void tx_rf(RU_t *ru,
|
||||
LOG_E(PHY,"%d.%d late_control : %d\n",frame,subframe,late_control);
|
||||
switch (late_control) {
|
||||
case STATE_BURST_TERMINATE:
|
||||
flags=10; // end of burst and no time spec
|
||||
flags = TX_BURST_END_NO_TIME_SPEC;
|
||||
late_control=STATE_BURST_STOP_1;
|
||||
break;
|
||||
|
||||
case STATE_BURST_STOP_1:
|
||||
flags=0; // no send
|
||||
flags = TX_BURST_INVALID;
|
||||
late_control=STATE_BURST_STOP_2;
|
||||
return;//no send
|
||||
break;
|
||||
|
||||
case STATE_BURST_STOP_2:
|
||||
flags=0; // no send
|
||||
flags = TX_BURST_INVALID;
|
||||
late_control=STATE_BURST_RESTART;
|
||||
return;//no send
|
||||
break;
|
||||
|
||||
case STATE_BURST_RESTART:
|
||||
flags=2; // start burst
|
||||
flags = TX_BURST_START;
|
||||
late_control=STATE_BURST_NORMAL;
|
||||
break;
|
||||
|
||||
|
||||
@@ -694,7 +694,8 @@ void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) {
|
||||
|
||||
if ((SF_type == SF_DL) ||
|
||||
(SF_type == SF_S)) {
|
||||
int siglen=fp->samples_per_tti,flags=1;
|
||||
int siglen=fp->samples_per_tti;
|
||||
radio_tx_burst_flag_t flags = TX_BURST_MIDDLE;
|
||||
|
||||
if (SF_type == SF_S) {
|
||||
/* end_of_burst_delay is used to stop TX only "after a while".
|
||||
@@ -707,13 +708,13 @@ void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) {
|
||||
siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
|
||||
+ (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
|
||||
+ ru->end_of_burst_delay;
|
||||
flags=3; // end of burst
|
||||
flags = TX_BURST_END;
|
||||
}
|
||||
|
||||
if (fp->frame_type == TDD &&
|
||||
SF_type == SF_DL &&
|
||||
prevSF_type == SF_UL) {
|
||||
flags = 2; // start of burst
|
||||
flags = TX_BURST_START;
|
||||
sf_extension = ru->sf_extension;
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ void rx_func(void *param) {
|
||||
stop_meas(&gNB->ul_indication_stats);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg,frame_rx,slot_tx);
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
|
||||
if ((tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) && NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
notifiedFIFO_elt_t *res;
|
||||
processingData_L1tx_t *syncMsg;
|
||||
// Its a FIFO so it maitains the order in which the MAC fills the messages
|
||||
@@ -470,7 +470,7 @@ void init_gNB_Tpool(int inst) {
|
||||
pushNotifiedFIFO(&gNB->L1_tx_free, msgL1Tx); // to unblock the process in the beginning
|
||||
}
|
||||
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT))
|
||||
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT) && (NFAPI_MODE!=NFAPI_MODE_VNF))
|
||||
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
|
||||
|
||||
LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
|
||||
|
||||
+21
-28
@@ -733,7 +733,8 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
T_INT(0), T_BUFFER(&ru->common.txdata[0][fp->get_samples_slot_timestamp(slot,fp,0)], fp->samples_per_subframe * 4));
|
||||
int sf_extension = 0;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
int flags = 0;
|
||||
radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID;
|
||||
radio_tx_gpio_flag_t flags_gpio = 0;
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx) {
|
||||
int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
|
||||
@@ -760,49 +761,41 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
}
|
||||
|
||||
//+ ru->end_of_burst_delay;
|
||||
flags = 3; // end of burst
|
||||
flags_burst = TX_BURST_END;
|
||||
} else if (slot_type == NR_DOWNLINK_SLOT) {
|
||||
int prevslot_type = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
|
||||
int nextslot_type = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
|
||||
if (prevslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 2; // start of burst
|
||||
flags_burst = TX_BURST_START;
|
||||
sf_extension = ru->sf_extension;
|
||||
} else if (nextslot_type == NR_UPLINK_SLOT) {
|
||||
flags = 3; // end of burst
|
||||
flags_burst = TX_BURST_END;
|
||||
} else {
|
||||
flags = 1; // middle of burst
|
||||
flags_burst = TX_BURST_MIDDLE;
|
||||
}
|
||||
}
|
||||
} else { // FDD
|
||||
if (proc->first_tx == 1) {
|
||||
flags = 2; // start of burst
|
||||
} else {
|
||||
flags = 1; // middle of burst
|
||||
}
|
||||
flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE;
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
if (fp->freq_range==nr_FR2) {
|
||||
// the beam index is written in bits 8-10 of the flags
|
||||
// bit 11 enables the gpio programming
|
||||
// currently we switch beams every 10 slots (should = 1 TDD period in FR2) and we take the beam index of the first symbol of the first slot of this period
|
||||
int beam=0;
|
||||
// currently we switch beams at the beginning of a slot and we take the beam index of the first symbol of this slot
|
||||
// we only send the beam to the gpio if the beam is different from the previous slot
|
||||
|
||||
if (slot%10==0) {
|
||||
if ( ru->common.beam_id && (ru->common.beam_id[0][slot*fp->symbols_per_slot] < 8)) {
|
||||
beam = ru->common.beam_id[0][slot*fp->symbols_per_slot] | 8;
|
||||
if ( ru->common.beam_id) {
|
||||
int prev_slot = (slot - 1 + fp->slots_per_frame) % fp->slots_per_frame;
|
||||
const uint8_t *beam_ids = ru->common.beam_id[0];
|
||||
int prev_beam = beam_ids[prev_slot * fp->symbols_per_slot];
|
||||
int beam = beam_ids[slot * fp->symbols_per_slot];
|
||||
if (prev_beam != beam) {
|
||||
flags_gpio = beam | TX_GPIO_CHANGE; // enable change of gpio
|
||||
LOG_D(HW, "slot %d, beam %d\n", slot, ru->common.beam_id[0][slot * fp->symbols_per_slot]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (slot==0 || slot==40) beam=0|8;
|
||||
if (slot==10 || slot==50) beam=1|8;
|
||||
if (slot==20 || slot==60) beam=2|8;
|
||||
if (slot==30 || slot==70) beam=3|8;
|
||||
*/
|
||||
flags |= beam<<8;
|
||||
LOG_D(HW,"slot %d, beam %d\n",slot,ru->common.beam_id[0][slot*fp->symbols_per_slot]);
|
||||
}
|
||||
|
||||
const int flags = flags_burst | flags_gpio << 4;
|
||||
|
||||
if (proc->first_tx == 1) proc->first_tx = 0;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags );
|
||||
@@ -825,7 +818,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
(long long unsigned int)(timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension),frame,slot,proc->frame_tx_unwrap,slot, flags, siglen+sf_extension, txs,10*log10((double)signal_energy(txp[0],siglen+sf_extension)));
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
//AssertFatal(txs == 0,"trx write function error %d\n", txs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// this is for RU with local RF unit
|
||||
|
||||
@@ -581,8 +581,10 @@ int main( int argc, char **argv ) {
|
||||
RCconfig_NR_L1();
|
||||
|
||||
// don't create if node doesn't connect to RRC/S1/GTP
|
||||
int ret=create_gNB_tasks(1);
|
||||
AssertFatal(ret==0,"cannot create ITTI tasks\n");
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
int ret = create_gNB_tasks(1);
|
||||
AssertFatal(ret == 0, "cannot create ITTI tasks\n");
|
||||
}
|
||||
|
||||
// init UE_PF_PO and mutex lock
|
||||
pthread_mutex_init(&ue_pf_po_mutex, NULL);
|
||||
@@ -598,28 +600,6 @@ int main( int argc, char **argv ) {
|
||||
pthread_mutex_init(&sync_mutex, NULL);
|
||||
}
|
||||
|
||||
const char *nfapi_mode_str = "<UNKNOWN>";
|
||||
|
||||
switch(NFAPI_MODE) {
|
||||
case 0:
|
||||
nfapi_mode_str = "MONOLITHIC";
|
||||
break;
|
||||
|
||||
case 1:
|
||||
nfapi_mode_str = "PNF";
|
||||
break;
|
||||
|
||||
case 2:
|
||||
nfapi_mode_str = "VNF";
|
||||
break;
|
||||
|
||||
default:
|
||||
nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("NFAPI MODE:%s\n", nfapi_mode_str);
|
||||
|
||||
printf("START MAIN THREADS\n");
|
||||
// start the main threads
|
||||
number_of_cards = 1;
|
||||
|
||||
+5
-5
@@ -509,7 +509,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
txp[i] = (void *)&UE->common_vars.txdata[i][UE->frame_parms.get_samples_slot_timestamp(
|
||||
proc->nr_slot_tx, &UE->frame_parms, 0)];
|
||||
|
||||
radio_tx_flag_t flags = Invalid;
|
||||
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(0);
|
||||
|
||||
@@ -531,13 +531,13 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD) {
|
||||
uint8_t first_tx_slot = tdd_period - num_UL_slots;
|
||||
|
||||
if (slot_tx_usrp % tdd_period == first_tx_slot)
|
||||
flags = StartOfBurst;
|
||||
flags = TX_BURST_START;
|
||||
else if (slot_tx_usrp % tdd_period == first_tx_slot + num_UL_slots - 1)
|
||||
flags = EndOfBurst;
|
||||
flags = TX_BURST_END;
|
||||
else if (slot_tx_usrp % tdd_period > first_tx_slot)
|
||||
flags = MiddleOfBurst;
|
||||
flags = TX_BURST_MIDDLE;
|
||||
} else {
|
||||
flags = MiddleOfBurst;
|
||||
flags = TX_BURST_MIDDLE;
|
||||
}
|
||||
|
||||
if (flags || IS_SOFTMODEM_RFSIM)
|
||||
|
||||
@@ -98,17 +98,25 @@ void get_common_options(uint32_t execmask) {
|
||||
uint32_t start_websrv = 0;
|
||||
uint32_t noS1 = 0, nokrnmod = 1, nonbiot = 0;
|
||||
uint32_t rfsim = 0, do_forms = 0;
|
||||
int nfapi_index = 0;
|
||||
char *logmem_filename = NULL;
|
||||
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
|
||||
check_execmask(execmask);
|
||||
|
||||
paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC;
|
||||
checkedparam_t cmdline_CheckParams[] = CMDLINE_PARAMS_CHECK_DESC;
|
||||
int numparams = sizeof(cmdline_params) / sizeof(paramdef_t);
|
||||
config_set_checkfunctions(cmdline_params, cmdline_CheckParams, numparams);
|
||||
config_get(cmdline_params, sizeof(cmdline_params) / sizeof(paramdef_t), NULL);
|
||||
nfapi_index = config_paramidx_fromname(cmdline_params, sizeof(cmdline_params) / sizeof(paramdef_t),"nfapi");
|
||||
AssertFatal(nfapi_index != -1,"Index for nfapi config option not found!");
|
||||
nfapi_mode = config_get_processedint(&cmdline_params[nfapi_index]);
|
||||
|
||||
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
|
||||
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
|
||||
check_execmask(execmask);
|
||||
config_get( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
|
||||
|
||||
int numparams=sizeof(cmdline_logparams)/sizeof(paramdef_t);
|
||||
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams,numparams);
|
||||
config_get( cmdline_logparams,numparams,NULL);
|
||||
|
||||
int numlogparams = sizeof(cmdline_logparams) / sizeof(paramdef_t);
|
||||
config_set_checkfunctions(cmdline_logparams, cmdline_log_CheckParams, numlogparams);
|
||||
config_get(cmdline_logparams, numlogparams, NULL);
|
||||
|
||||
if(config_isparamset(cmdline_logparams,config_paramidx_fromname(cmdline_logparams,numparams, CONFIG_FLOG_OPT))) {
|
||||
set_glog_onlinelog(online_log_messages);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ extern "C"
|
||||
#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_USRP_THREAD "having extra thead for usrp tx\n"
|
||||
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n"
|
||||
#define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR 'MONOLITHIC', 'PNF', 'VNF','UE_STUB_PNF','UE_STUB_OFFNET','STANDALONE_PNF'\n"
|
||||
#define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n"
|
||||
#define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n"
|
||||
#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence"
|
||||
@@ -167,13 +167,58 @@ extern int usrp_tx_thread;
|
||||
{"nsa", CONFIG_HLP_NSA, PARAMFLAG_BOOL, iptr:&NSA, defintval:0, TYPE_INT, 0}, \
|
||||
{"node-number", NULL, 0, u16ptr:&NODE_NUMBER, defuintval:0, TYPE_UINT16, 0}, \
|
||||
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, iptr:&usrp_tx_thread, defstrval:0, TYPE_INT, 0}, \
|
||||
{"nfapi", CONFIG_HLP_NFAPI, 0, u8ptr:&nfapi_mode, defintval:0, TYPE_UINT8, 0}, \
|
||||
{"nfapi", CONFIG_HLP_NFAPI, 0, strptr:NULL, defstrval:"MONOLITHIC", TYPE_STRING, 0}, \
|
||||
{"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, iptr:&NON_STOP, defintval:0, TYPE_INT, 0}, \
|
||||
{"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, iptr:&EMULATE_L1, defintval:0, TYPE_INT, 0}, \
|
||||
{"continuous-tx", CONFIG_HLP_CONTINUOUS_TX,PARAMFLAG_BOOL, iptr:&CONTINUOUS_TX, defintval:0, TYPE_INT, 0}, \
|
||||
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, iptr:&stats_disabled, defintval:0, TYPE_INT, 0}, \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CMDLINE_PARAMS_CHECK_DESC { \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s3a = { config_checkstr_assign_integer, \
|
||||
{"MONOLITHIC", "PNF", "VNF","UE_STUB_PNF","UE_STUB_OFFNET","STANDALONE_PNF"}, \
|
||||
{NFAPI_MONOLITHIC, NFAPI_MODE_PNF, NFAPI_MODE_VNF,NFAPI_UE_STUB_PNF,NFAPI_UE_STUB_OFFNET,NFAPI_MODE_STANDALONE_PNF}, \
|
||||
6 } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
|
||||
#define CONFIG_HLP_NSA "Enable NSA mode \n"
|
||||
#define CONFIG_HLP_FLOG "Enable online log \n"
|
||||
#define CONFIG_HLP_LOGL "Set the global log level, valid options: (4:trace, 3:debug, 2:info, 1:warn, (0:error))\n"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
echo "building ctags for openair1 and openair2 ..."
|
||||
ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables
|
||||
ctags -e -R --exclude=openair1/DOCS/ --exclude=openair2/DOCS/ --exclude=openair1/SIMULATION/ --exclude=targets/DOCS/ --exclude=targets/PROJECTS/ openair1 openair2 openair3 targets cmake_targets common nfapi executables sdr
|
||||
|
||||
|
||||
@@ -548,13 +548,12 @@ int pnf_stop_request(nfapi_pnf_config_t *config, nfapi_pnf_stop_request_t *req)
|
||||
|
||||
int param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_param_request_t *req) {
|
||||
printf("[PNF] Received NFAPI_PARAM_REQUEST phy_id:%d\n", req->header.phy_id);
|
||||
//pnf_info* pnf = (pnf_info*)(config->user_data);
|
||||
nfapi_param_response_t nfapi_resp;
|
||||
pnf_info *pnf = (pnf_info *)(config->user_data);
|
||||
memset(&nfapi_resp, 0, sizeof(nfapi_resp));
|
||||
nfapi_resp.header.message_id = NFAPI_PARAM_RESPONSE;
|
||||
nfapi_resp.header.phy_id = req->header.phy_id;
|
||||
nfapi_resp.error_code = 0; // DJP - what value???
|
||||
nfapi_resp.error_code = 0;
|
||||
struct sockaddr_in pnf_p7_sockaddr;
|
||||
pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(pnf->phys[0].local_addr);
|
||||
nfapi_resp.nfapi_config.p7_pnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG;
|
||||
@@ -562,7 +561,7 @@ int param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
|
||||
nfapi_resp.num_tlv++;
|
||||
// P7 PNF Port
|
||||
nfapi_resp.nfapi_config.p7_pnf_port.tl.tag = NFAPI_NFAPI_P7_PNF_PORT_TAG;
|
||||
nfapi_resp.nfapi_config.p7_pnf_port.value = 32123; // DJP - hard code alert!!!! FIXME TODO
|
||||
nfapi_resp.nfapi_config.p7_pnf_port.value = htons(pnf->phys[0].udp.rx_port);
|
||||
nfapi_resp.num_tlv++;
|
||||
nfapi_pnf_param_resp(config, &nfapi_resp);
|
||||
printf("[PNF] Sent NFAPI_PARAM_RESPONSE phy_id:%d number_of_tlvs:%u\n", req->header.phy_id, nfapi_resp.num_tlv);
|
||||
@@ -572,13 +571,12 @@ int param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
|
||||
|
||||
int nr_param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi_nr_param_request_scf_t *req) {
|
||||
printf("[PNF] Received NFAPI_PARAM_REQUEST phy_id:%d\n", req->header.phy_id);
|
||||
//pnf_info* pnf = (pnf_info*)(config->user_data);
|
||||
nfapi_nr_param_response_scf_t nfapi_resp;
|
||||
pnf_info *pnf = (pnf_info *)(config->user_data);
|
||||
memset(&nfapi_resp, 0, sizeof(nfapi_resp));
|
||||
nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_PARAM_RESPONSE;
|
||||
nfapi_resp.header.phy_id = req->header.phy_id;
|
||||
nfapi_resp.error_code = 0; // DJP - what value???
|
||||
nfapi_resp.error_code = 0;
|
||||
struct sockaddr_in pnf_p7_sockaddr;
|
||||
|
||||
// ASSIGN TAGS
|
||||
@@ -775,7 +773,7 @@ int nr_param_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nf
|
||||
nfapi_resp.num_tlv++;
|
||||
}
|
||||
|
||||
nfapi_resp.nfapi_config.p7_pnf_port.value = 32123; //pnf->phys[0].local_port; DJP - hard code alert!!!! FIXME TODO
|
||||
nfapi_resp.nfapi_config.p7_pnf_port.value = htons(pnf->phys[0].udp.rx_port);
|
||||
nfapi_resp.num_tlv++;
|
||||
pnf_p7_sockaddr.sin_addr.s_addr = inet_addr(pnf->phys[0].local_addr);
|
||||
|
||||
@@ -877,7 +875,7 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap
|
||||
num_tlv++;
|
||||
}
|
||||
|
||||
fp->num_MBSFN_config = 0; // DJP - hard code alert
|
||||
fp->num_MBSFN_config = 0; // hard code alert
|
||||
|
||||
if (req->sch_config.physical_cell_id.tl.tag == NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG) {
|
||||
fp->Nid_cell = req->sch_config.physical_cell_id.value;
|
||||
@@ -929,13 +927,13 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap
|
||||
}
|
||||
|
||||
if (req->pusch_config.hopping_mode.tl.tag == NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG) {
|
||||
} // DJP - not being handled?
|
||||
} // not being handled?
|
||||
|
||||
if (req->pusch_config.hopping_offset.tl.tag == NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG) {
|
||||
} // DJP - not being handled?
|
||||
} // not being handled?
|
||||
|
||||
if (req->pusch_config.number_of_subbands.tl.tag == NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG) {
|
||||
} // DJP - not being handled?
|
||||
} // not being handled?
|
||||
|
||||
if (req->prach_config.configuration_index.tl.tag == NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG) {
|
||||
fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=req->prach_config.configuration_index.value;
|
||||
@@ -964,7 +962,7 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap
|
||||
|
||||
if(NFAPI_MODE!=NFAPI_UE_STUB_PNF && NFAPI_MODE!=NFAPI_MODE_STANDALONE_PNF) {
|
||||
printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv);
|
||||
printf("[PNF] Simulating PHY CONFIG - DJP\n");
|
||||
printf("[PNF] Simulating PHY CONFIG\n");
|
||||
PHY_Config_t phy_config;
|
||||
phy_config.Mod_id = 0;
|
||||
phy_config.CC_id=0;
|
||||
@@ -982,7 +980,7 @@ int config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfap
|
||||
memset(&nfapi_resp, 0, sizeof(nfapi_resp));
|
||||
nfapi_resp.header.message_id = NFAPI_CONFIG_RESPONSE;
|
||||
nfapi_resp.header.phy_id = phy_info->id;
|
||||
nfapi_resp.error_code = 0; // DJP - some value resp->error_code;
|
||||
nfapi_resp.error_code = 0;
|
||||
nfapi_pnf_config_resp(config, &nfapi_resp);
|
||||
printf("[PNF] Sent NFAPI_CONFIG_RESPONSE phy_id:%d\n", phy_info->id);
|
||||
|
||||
@@ -1058,7 +1056,7 @@ int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n
|
||||
|
||||
if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
|
||||
printf("[PNF] CONFIG_REQUEST[num_tlv:%d] TLVs processed:%d\n", req->num_tlv, num_tlv);
|
||||
printf("[PNF] Simulating PHY CONFIG - DJP\n");
|
||||
printf("[PNF] Simulating PHY CONFIG\n");
|
||||
NR_PHY_Config_t nr_phy_config;
|
||||
nr_phy_config.Mod_id = 0;
|
||||
nr_phy_config.CC_id=0;
|
||||
@@ -1076,7 +1074,7 @@ int nr_config_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n
|
||||
memset(&nfapi_resp, 0, sizeof(nfapi_resp));
|
||||
nfapi_resp.header.message_id = NFAPI_NR_PHY_MSG_TYPE_CONFIG_RESPONSE;
|
||||
nfapi_resp.header.phy_id = phy_info->id;
|
||||
nfapi_resp.error_code = 0; // DJP - some value resp->error_code;
|
||||
nfapi_resp.error_code = 0;
|
||||
nfapi_nr_pnf_config_resp(config, &nfapi_resp);
|
||||
printf("[PNF] Sent NFAPI_PNF_CONFIG_RESPONSE phy_id:%d\n", phy_info->id);
|
||||
|
||||
@@ -1630,8 +1628,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
|
||||
p7_config->phy_id = phy->phy_id;
|
||||
p7_config->remote_p7_port = phy_info->remote_port;
|
||||
p7_config->remote_p7_addr = phy_info->remote_addr;
|
||||
p7_config->local_p7_port = 32123;//phy_info->local_port;//50010; // DJP - good grief cannot seem to get the right answer phy_info->local_port;
|
||||
//DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str();
|
||||
p7_config->local_p7_port = phy_info->udp.rx_port;
|
||||
p7_config->local_p7_addr = phy_info->local_addr;
|
||||
printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port);
|
||||
p7_config->user_data = phy_info;
|
||||
@@ -1702,7 +1699,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
|
||||
//((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__);
|
||||
l1_north_init_eNB();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
|
||||
p7_config_g = p7_config;
|
||||
|
||||
// Need to wait for main thread to create RU structures
|
||||
@@ -1736,7 +1733,7 @@ int start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, nfapi
|
||||
printf("[PNF] Sending PNF_START_RESP\n");
|
||||
nfapi_send_pnf_start_resp(config, p7_config->phy_id);
|
||||
printf("[PNF] Sending first P7 subframe ind\n");
|
||||
nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct???
|
||||
nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct???
|
||||
printf("[PNF] Sent first P7 subframe ind\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1749,9 +1746,8 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n
|
||||
p7_config->phy_id = phy->phy_id;
|
||||
p7_config->remote_p7_port = phy_info->remote_port;
|
||||
p7_config->remote_p7_addr = phy_info->remote_addr;
|
||||
// TODO: remove this hardcoded port
|
||||
p7_config->local_p7_port = 32123; // DJP - good grief cannot seem to get the right answer phy_info->local_port;
|
||||
//DJP p7_config->local_p7_addr = (char*)phy_info->local_addr.c_str();
|
||||
|
||||
p7_config->local_p7_port = phy_info->udp.rx_port;
|
||||
p7_config->local_p7_addr = phy_info->local_addr;
|
||||
printf("[PNF] P7 remote:%s:%d local:%s:%d\n", p7_config->remote_p7_addr, p7_config->remote_p7_port, p7_config->local_p7_addr, p7_config->local_p7_port);
|
||||
p7_config->user_data = phy_info;
|
||||
@@ -1827,10 +1823,9 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Creating P7 thread %s\n", __FUNCTION__);
|
||||
pthread_t p7_thread;
|
||||
pthread_create(&p7_thread, NULL, &pnf_nr_p7_thread_start, p7_config);
|
||||
//((pnf_phy_user_data_t*)(phy_info->fapi->user_data))->p7_config = p7_config;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] Calling l1_north_init_eNB() %s\n", __FUNCTION__);
|
||||
l1_north_init_gNB();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] DJP - HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[PNF] HACK - Set p7_config global ready for subframe ind%s\n", __FUNCTION__);
|
||||
p7_config_g = p7_config;
|
||||
|
||||
// Need to wait for main thread to create RU structures
|
||||
@@ -1868,7 +1863,7 @@ int nr_start_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t *phy, n
|
||||
nfapi_pnf_p7_slot_ind(p7_config, p7_config->phy_id, 0, 0);
|
||||
printf("[PNF] Sent first P7 slot ind\n");
|
||||
#else
|
||||
nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // DJP - SFN_SF set to zero - correct???
|
||||
nfapi_pnf_p7_subframe_ind(p7_config, p7_config->phy_id, 0); // SFN_SF set to zero - correct???
|
||||
printf("[PNF] Sent first P7 subframe ind\n");
|
||||
#endif
|
||||
|
||||
@@ -1982,8 +1977,6 @@ int broadcast_detect_request(nfapi_pnf_config_t *config, nfapi_pnf_phy_config_t
|
||||
case NFAPI_RAT_TYPE_UTRAN: {
|
||||
ind.utran_broadcast_detect_indication.tl.tag = NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG;
|
||||
ind.utran_broadcast_detect_indication.mib_length = 4;
|
||||
//ind.utran_broadcast_detect_indication.mib...
|
||||
// ind.utran_broadcast_detect_indication.sfn_offset; DJP - nonsense line
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2149,7 +2142,7 @@ void configure_nr_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_add
|
||||
config->vnf_ip_addr = vnf_ip_addr;
|
||||
config->vnf_p5_port = vnf_p5_port;
|
||||
pnf.phys[0].udp.enabled = 1;
|
||||
pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port;
|
||||
pnf.phys[0].udp.rx_port = pnf_p7_port;
|
||||
pnf.phys[0].udp.tx_port = vnf_p7_port;
|
||||
strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr);
|
||||
strcpy(pnf.phys[0].local_addr, pnf_ip_addr);
|
||||
@@ -2200,7 +2193,7 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr,
|
||||
config->vnf_ip_addr = vnf_ip_addr;
|
||||
config->vnf_p5_port = vnf_p5_port;
|
||||
pnf.phys[0].udp.enabled = 1;
|
||||
pnf.phys[0].udp.rx_port = 32123;//pnf_p7_port;
|
||||
pnf.phys[0].udp.rx_port = pnf_p7_port;
|
||||
pnf.phys[0].udp.tx_port = vnf_p7_port;
|
||||
strcpy(pnf.phys[0].udp.tx_addr, vnf_ip_addr);
|
||||
strcpy(pnf.phys[0].local_addr, pnf_ip_addr);
|
||||
@@ -2242,7 +2235,7 @@ void configure_nfapi_pnf(char *vnf_ip_addr, int vnf_p5_port, char *pnf_ip_addr,
|
||||
void oai_subframe_ind(uint16_t sfn, uint16_t sf) {
|
||||
//LOG_D(PHY,"%s(sfn:%d, sf:%d)\n", __FUNCTION__, sfn, sf);
|
||||
|
||||
//TODO FIXME - HACK - DJP - using a global to bodge it in
|
||||
//TODO FIXME - HACK - using a global to bodge it in
|
||||
if (p7_config_g != NULL && sync_var==0) {
|
||||
uint16_t sfn_sf_tx = sfn<<4 | sf;
|
||||
|
||||
@@ -2282,13 +2275,13 @@ void handle_nr_slot_ind(uint16_t sfn, uint16_t slot) {
|
||||
}
|
||||
|
||||
int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind) {
|
||||
rach_ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
rach_ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
LOG_D(PHY, "%s() sfn_sf:%d preambles:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(rach_ind->sfn_sf), rach_ind->rach_indication_body.number_of_preambles);
|
||||
return nfapi_pnf_p7_rach_ind(p7_config_g, rach_ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind) {
|
||||
harq_ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
harq_ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
harq_ind->header.message_id = NFAPI_HARQ_INDICATION;
|
||||
LOG_D(PHY, "%s() sfn_sf:%d number_of_harqs:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(harq_ind->sfn_sf), harq_ind->harq_indication_body.number_of_harqs);
|
||||
int retval = nfapi_pnf_p7_harq_ind(p7_config_g, harq_ind);
|
||||
@@ -2300,21 +2293,21 @@ int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind) {
|
||||
}
|
||||
|
||||
int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind) {
|
||||
crc_ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
crc_ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
crc_ind->header.message_id = NFAPI_CRC_INDICATION;
|
||||
//LOG_D(PHY, "%s() sfn_sf:%d number_of_crcs:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(crc_ind->sfn_sf), crc_ind->crc_indication_body.number_of_crcs);
|
||||
return nfapi_pnf_p7_crc_ind(p7_config_g, crc_ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_RX_CQI_INDICATION;
|
||||
//LOG_D(PHY, "%s() sfn_sf:%d number_of_cqis:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->cqi_indication_body.number_of_cqis);
|
||||
return nfapi_pnf_p7_cqi_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_RX_ULSCH_INDICATION;
|
||||
int retval = nfapi_pnf_p7_rx_ind(p7_config_g, ind);
|
||||
//LOG_D(PHY,"%s() SFN/SF:%d pdus:%d retval:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->rx_indication_body.number_of_pdus, retval);
|
||||
@@ -2323,7 +2316,7 @@ int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind) {
|
||||
}
|
||||
|
||||
int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
int retval = nfapi_pnf_p7_sr_ind(p7_config_g, ind);
|
||||
//LOG_D(PHY,"%s() SFN/SF:%d srs:%d retval:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->sr_indication_body.number_of_srs, retval);
|
||||
//free(ind.rx_indication_body.rx_pdu_list);
|
||||
@@ -2339,31 +2332,31 @@ int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind) {
|
||||
}
|
||||
|
||||
int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RX_DATA_INDICATION;
|
||||
return nfapi_pnf_p7_nr_rx_data_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_CRC_INDICATION;
|
||||
return nfapi_pnf_p7_nr_crc_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_SRS_INDICATION;
|
||||
return nfapi_pnf_p7_nr_srs_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UCI_INDICATION;
|
||||
return nfapi_pnf_p7_nr_uci_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind) {
|
||||
ind->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ind->header.message_id = NFAPI_NR_PHY_MSG_TYPE_RACH_INDICATION;
|
||||
return nfapi_pnf_p7_nr_rach_ind(p7_config_g, ind);
|
||||
}
|
||||
|
||||
@@ -335,8 +335,8 @@ int pnf_nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_pnf_pa
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
|
||||
req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
|
||||
req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "DJP:Hard coded num phy rf to 2\n");
|
||||
req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // pnf.phys.size();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Hard coded num phy rf to 2\n");
|
||||
|
||||
for(unsigned i = 0; i < 2; ++i) {
|
||||
req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id;
|
||||
@@ -378,8 +378,8 @@ int pnf_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_param_re
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.header.message_id = NFAPI_PNF_CONFIG_REQUEST;
|
||||
req.pnf_phy_rf_config.tl.tag = NFAPI_PNF_PHY_RF_TAG;
|
||||
req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // DJP pnf.phys.size();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "DJP:Hard coded num phy rf to 2\n");
|
||||
req.pnf_phy_rf_config.number_phy_rf_config_info = 2; // pnf.phys.size();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "Hard coded num phy rf to 2\n");
|
||||
|
||||
for(unsigned i = 0; i < 2; ++i) {
|
||||
req.pnf_phy_rf_config.phy_rf_config[i].phy_id = pnf->phys[i].id;
|
||||
@@ -1574,7 +1574,7 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp
|
||||
phy_info *phy = pnf->phys;
|
||||
struct sockaddr_in pnf_p7_sockaddr;
|
||||
nfapi_nr_config_request_scf_t *req = &RC.nrmac[0]->config[0]; // check
|
||||
phy->remote_port = 50610;//resp->nfapi_config.p7_pnf_port.value;
|
||||
phy->remote_port = resp->nfapi_config.p7_pnf_port.value;
|
||||
//phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value;
|
||||
memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4);
|
||||
phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr);
|
||||
@@ -1589,13 +1589,13 @@ int nr_param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_nr_param_resp
|
||||
req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NR_NFAPI_P7_VNF_PORT_TAG;
|
||||
req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port;
|
||||
req->num_tlv++;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_port:%d\n", p7_vnf->local_port);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Local_port:%d\n", ntohs(p7_vnf->local_port));
|
||||
req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NR_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
|
||||
struct sockaddr_in vnf_p7_sockaddr;
|
||||
vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr);
|
||||
memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4);
|
||||
req->num_tlv++;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_addr:%s\n", p7_vnf->local_addr);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Local_addr:%s\n", p7_vnf->local_addr);
|
||||
req->nfapi_config.timing_window.tl.tag = NFAPI_NR_NFAPI_TIMING_WINDOW_TAG;
|
||||
req->nfapi_config.timing_window.value = p7_vnf->timing_window;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "\n[VNF]Timing window tag : %d Timing window:%u\n",NFAPI_NR_NFAPI_TIMING_WINDOW_TAG, p7_vnf->timing_window);
|
||||
@@ -1637,7 +1637,7 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t
|
||||
phy_info *phy = pnf->phys;
|
||||
struct sockaddr_in pnf_p7_sockaddr;
|
||||
nfapi_config_request_t *req = &RC.mac[0]->config[0];
|
||||
phy->remote_port = 32123;//resp->nfapi_config.p7_pnf_port.value;
|
||||
phy->remote_port = resp->nfapi_config.p7_pnf_port.value;
|
||||
memcpy(&pnf_p7_sockaddr.sin_addr.s_addr, &(resp->nfapi_config.p7_pnf_address_ipv4.address[0]), 4);
|
||||
phy->remote_addr = inet_ntoa(pnf_p7_sockaddr.sin_addr);
|
||||
// for now just 1
|
||||
@@ -1649,13 +1649,13 @@ int param_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_param_response_t
|
||||
req->nfapi_config.p7_vnf_port.tl.tag = NFAPI_NFAPI_P7_VNF_PORT_TAG;
|
||||
req->nfapi_config.p7_vnf_port.value = p7_vnf->local_port;
|
||||
req->num_tlv++;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_port:%d\n", p7_vnf->local_port);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Local_port:%d\n", ntohs(p7_vnf->local_port));
|
||||
req->nfapi_config.p7_vnf_address_ipv4.tl.tag = NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG;
|
||||
struct sockaddr_in vnf_p7_sockaddr;
|
||||
vnf_p7_sockaddr.sin_addr.s_addr = inet_addr(p7_vnf->local_addr);
|
||||
memcpy(&(req->nfapi_config.p7_vnf_address_ipv4.address[0]), &vnf_p7_sockaddr.sin_addr.s_addr, 4);
|
||||
req->num_tlv++;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] DJP local_addr:%s\n", p7_vnf->local_addr);
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Local_addr:%s\n", p7_vnf->local_addr);
|
||||
req->nfapi_config.timing_window.tl.tag = NFAPI_NFAPI_TIMING_WINDOW_TAG;
|
||||
req->nfapi_config.timing_window.value = p7_vnf->timing_window;
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Timing window:%u\n", p7_vnf->timing_window);
|
||||
@@ -1788,7 +1788,7 @@ void vnf_start_thread(void *ptr) {
|
||||
|
||||
static vnf_info vnf;
|
||||
|
||||
void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) {
|
||||
nfapi_setmode(NFAPI_MODE_VNF);
|
||||
memset(&vnf, 0, sizeof(vnf));
|
||||
memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs));
|
||||
@@ -1799,9 +1799,7 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port);
|
||||
strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr);
|
||||
//vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode
|
||||
vnf.p7_vnfs[0].local_port = 50611;
|
||||
//vnf.p7_vnfs[0].local_port = 50011;
|
||||
vnf.p7_vnfs[0].local_port = vnf_p7_port;
|
||||
vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t));
|
||||
nfapi_vnf_config_t *config = nfapi_vnf_config_create();
|
||||
config->malloc = malloc;
|
||||
@@ -1839,7 +1837,7 @@ void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
}
|
||||
|
||||
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port) {
|
||||
nfapi_setmode(NFAPI_MODE_VNF);
|
||||
memset(&vnf, 0, sizeof(vnf));
|
||||
memset(vnf.p7_vnfs, 0, sizeof(vnf.p7_vnfs));
|
||||
@@ -1850,8 +1848,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
vnf.p7_vnfs[0].config = nfapi_vnf_p7_config_create();
|
||||
NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] %s() vnf.p7_vnfs[0].config:%p VNF ADDRESS:%s:%d\n", __FUNCTION__, vnf.p7_vnfs[0].config, vnf_addr, vnf_p5_port);
|
||||
strcpy(vnf.p7_vnfs[0].local_addr, vnf_addr);
|
||||
//vnf.p7_vnfs[0].local_port = vnf.p7_vnfs[0].local_port; // 50001; // TODO: remove hardcode
|
||||
vnf.p7_vnfs[0].local_port = 50011;
|
||||
vnf.p7_vnfs[0].local_port = vnf_p7_port;
|
||||
vnf.p7_vnfs[0].mac = (mac_t *)malloc(sizeof(mac_t));
|
||||
nfapi_vnf_config_t *config = nfapi_vnf_config_create();
|
||||
config->malloc = malloc;
|
||||
@@ -1890,7 +1887,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
|
||||
|
||||
int oai_nfapi_dl_config_req(nfapi_dl_config_request_t *dl_config_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
dl_config_req->header.message_id = NFAPI_DL_CONFIG_REQUEST;
|
||||
LOG_D(PHY, "[VNF] %s() DL_CONFIG_REQ sfn_sf:%d_%d number_of_pdus:%d\n", __FUNCTION__,
|
||||
NFAPI_SFNSF2SFN(dl_config_req->sfn_sf),NFAPI_SFNSF2SF(dl_config_req->sfn_sf), dl_config_req->dl_config_request_body.number_pdu);
|
||||
@@ -1927,7 +1924,7 @@ int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req)
|
||||
LOG_D(NR_PHY, "Entering oai_nfapi_nr_dl_config_req sfn:%d,slot:%d\n", dl_config_req->SFN, dl_config_req->Slot);
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
dl_config_req->header.message_id= NFAPI_NR_PHY_MSG_TYPE_DL_TTI_REQUEST;
|
||||
dl_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
dl_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
|
||||
int retval = nfapi_vnf_p7_nr_dl_config_req(p7_config, dl_config_req);
|
||||
|
||||
@@ -1945,7 +1942,7 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
{
|
||||
LOG_D(NR_PHY, "Entering oai_nfapi_nr_tx_data_req sfn:%d,slot:%d\n", tx_data_req->SFN, tx_data_req->Slot);
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
tx_data_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_data_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_data_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_TX_DATA_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus);
|
||||
int retval = nfapi_vnf_p7_tx_data_req(p7_config, tx_data_req);
|
||||
@@ -1962,7 +1959,7 @@ int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req)
|
||||
int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req)
|
||||
{
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
tx_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
tx_req->header.message_id = NFAPI_TX_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() TX_REQ sfn_sf:%d number_of_pdus:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(tx_req->sfn_sf), tx_req->tx_request_body.number_of_pdus);
|
||||
int retval = nfapi_vnf_p7_tx_req(p7_config, tx_req);
|
||||
@@ -1978,7 +1975,7 @@ int oai_nfapi_tx_req(nfapi_tx_request_t *tx_req)
|
||||
|
||||
int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
ul_dci_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_dci_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_dci_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_DCI_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi);
|
||||
int retval = nfapi_vnf_p7_ul_dci_req(p7_config, ul_dci_req);
|
||||
@@ -1994,7 +1991,7 @@ int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req) {
|
||||
|
||||
int oai_nfapi_hi_dci0_req(nfapi_hi_dci0_request_t *hi_dci0_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
hi_dci0_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
hi_dci0_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() HI_DCI0_REQ sfn_sf:%d dci:%d hi:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(hi_dci0_req->sfn_sf), hi_dci0_req->hi_dci0_request_body.number_of_dci, hi_dci0_req->hi_dci0_request_body.number_of_hi);
|
||||
int retval = nfapi_vnf_p7_hi_dci0_req(p7_config, hi_dci0_req);
|
||||
@@ -2031,7 +2028,7 @@ static void remove_ul_config_req_pdu(int index, nfapi_ul_config_request_t *ul_co
|
||||
int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
|
||||
ul_tti_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_tti_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_tti_req->header.message_id = NFAPI_NR_PHY_MSG_TYPE_UL_TTI_REQUEST;
|
||||
|
||||
int retval = nfapi_vnf_p7_ul_tti_req(p7_config, ul_tti_req);
|
||||
@@ -2050,7 +2047,7 @@ int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req) {
|
||||
|
||||
int oai_nfapi_ul_config_req(nfapi_ul_config_request_t *ul_config_req) {
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
ul_config_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_config_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
ul_config_req->header.message_id = NFAPI_UL_CONFIG_REQUEST;
|
||||
//LOG_D(PHY, "[VNF] %s() header message_id:%02x\n", __FUNCTION__, ul_config_req->header.message_id);
|
||||
//LOG_D(PHY, "[VNF] %s() UL_CONFIG sfn_sf:%d PDUs:%d rach_prach_frequency_resources:%d srs_present:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ul_config_req->sfn_sf), ul_config_req->ul_config_request_body.number_of_pdus, ul_config_req->ul_config_request_body.rach_prach_frequency_resources, ul_config_req->ul_config_request_body.srs_present);
|
||||
@@ -2111,7 +2108,7 @@ int oai_nfapi_ue_release_req(nfapi_ue_release_request_t *release_req){
|
||||
return 0;
|
||||
nfapi_vnf_p7_config_t *p7_config = vnf.p7_vnfs[0].config;
|
||||
|
||||
release_req->header.phy_id = 1; // DJP HACK TODO FIXME - need to pass this around!!!!
|
||||
release_req->header.phy_id = 1; // HACK TODO FIXME - need to pass this around!!!!
|
||||
release_req->header.message_id = NFAPI_UE_RELEASE_REQUEST;
|
||||
release_req->ue_release_request_body.tl.tag = NFAPI_UE_RELEASE_BODY_TAG;
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port);
|
||||
void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port);
|
||||
void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
|
||||
void configure_nr_nfapi_vnf(char *vnf_addr, int vnf_p5_port, char *pnf_ip_addr, int pnf_p7_port, int vnf_p7_port);
|
||||
|
||||
uint32_t sfnslot_add_slot(uint16_t sfn, uint16_t slot, int offset);
|
||||
|
||||
|
||||
@@ -967,7 +967,7 @@ int pnf_p7_slot_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn, uint16_t sl
|
||||
slot = shifted_slot;
|
||||
|
||||
//
|
||||
// DJP - why does the shift not apply to pnf_p7->sfn_sf???
|
||||
// why does the shift not apply to pnf_p7->sfn_sf???
|
||||
//
|
||||
|
||||
pnf_p7->slot_shift = 0;
|
||||
@@ -1219,7 +1219,7 @@ int pnf_p7_subframe_ind(pnf_p7_t* pnf_p7, uint16_t phy_id, uint16_t sfn_sf)
|
||||
sfn_sf = shifted_sfn_sf;
|
||||
|
||||
//
|
||||
// DJP - why does the shift not apply to pnf_p7->sfn_sf???
|
||||
// why does the shift not apply to pnf_p7->sfn_sf???
|
||||
//
|
||||
|
||||
pnf_p7->sfn_sf_shift = 0;
|
||||
@@ -2908,7 +2908,7 @@ void pnf_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_time)
|
||||
recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, pnf_p7->rx_message_buffer_size,
|
||||
MSG_DONTWAIT | MSG_TRUNC, (struct sockaddr*)&remote_addr, &remote_addr_size);
|
||||
|
||||
now_hr_time = pnf_get_current_time_hr(); //DJP - moved to here - get closer timestamp???
|
||||
now_hr_time = pnf_get_current_time_hr(); //moved to here - get closer timestamp???
|
||||
|
||||
if(recvfrom_result > 0)
|
||||
{
|
||||
@@ -2975,7 +2975,7 @@ void pnf_nr_nfapi_p7_read_dispatch_message(pnf_p7_t* pnf_p7, uint32_t now_hr_tim
|
||||
// read the segment
|
||||
recvfrom_result = recvfrom(pnf_p7->p7_sock, pnf_p7->rx_message_buffer, header.message_length, MSG_DONTWAIT, (struct sockaddr*)&remote_addr, &remote_addr_size);
|
||||
|
||||
now_hr_time = pnf_get_current_time_hr(); //DJP - moved to here - get closer timestamp???
|
||||
now_hr_time = pnf_get_current_time_hr(); //moved to here - get closer timestamp???
|
||||
|
||||
if(recvfrom_result > 0)
|
||||
{
|
||||
@@ -3060,7 +3060,7 @@ int pnf_p7_message_pump(pnf_p7_t* pnf_p7)
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = pnf_p7->_public.local_p7_port;
|
||||
addr.sin_port = htons(pnf_p7->_public.local_p7_port);
|
||||
|
||||
if(pnf_p7->_public.local_p7_addr == 0)
|
||||
{
|
||||
@@ -3232,7 +3232,7 @@ int pnf_nr_p7_message_pump(pnf_p7_t* pnf_p7)
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = pnf_p7->_public.local_p7_port;
|
||||
addr.sin_port = htons(pnf_p7->_public.local_p7_port);
|
||||
|
||||
if(pnf_p7->_public.local_p7_addr == 0)
|
||||
{
|
||||
|
||||
@@ -50,7 +50,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
|
||||
|
||||
int nr_slot_fep(PHY_VARS_NR_UE *ue,
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char l,
|
||||
unsigned char symbol,
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue,
|
||||
|
||||
@@ -722,11 +722,10 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][ue->frame_parms.ofdm_symbol_size],
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
|
||||
@@ -69,8 +69,8 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue,
|
||||
|
||||
int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
int estimateSz,
|
||||
struct complex16 dl_ch_estimates [][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time [][estimateSz],
|
||||
struct complex16 dl_ch_estimates[][estimateSz],
|
||||
struct complex16 dl_ch_estimates_time[][ue->frame_parms.ofdm_symbol_size],
|
||||
UE_nr_rxtx_proc_t *proc,
|
||||
unsigned char symbol,
|
||||
int dmrss,
|
||||
@@ -90,7 +90,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
|
||||
unsigned short bwp_start_subcarrier,
|
||||
unsigned short nb_rb_pdsch,
|
||||
uint32_t pdsch_est_size,
|
||||
int32_t pdsch_dl_ch_estimates[][pdsch_est_size],
|
||||
int32_t dl_ch_estimates[][pdsch_est_size],
|
||||
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
|
||||
|
||||
void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
|
||||
|
||||
@@ -43,6 +43,9 @@
|
||||
// 10*log10(pow(2,30))
|
||||
#define pow_2_30_dB 90
|
||||
|
||||
// Additional memory allocation, because of applying the filter and the memory offset to ensure memory alignment
|
||||
#define FILTER_MARGIN 32
|
||||
|
||||
//#define NR_CSIRS_DEBUG
|
||||
//#define NR_CSIIM_DEBUG
|
||||
|
||||
@@ -291,8 +294,9 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const uint8_t *j_cdm,
|
||||
const uint8_t *k_overline,
|
||||
const uint8_t *l_overline,
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_ls_estimated_channel[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
int16_t *log2_re,
|
||||
int16_t *log2_maxh,
|
||||
uint32_t *noise_power) {
|
||||
@@ -376,7 +380,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
/// Channel interpolation
|
||||
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
memset(csi_rs_estimated_channel_freq[ant_rx][port_tx], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t));
|
||||
memset(csi_rs_estimated_channel_freq[ant_rx][port_tx], 0, (frame_parms->ofdm_symbol_size + FILTER_MARGIN) * sizeof(int32_t));
|
||||
}
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
@@ -389,9 +393,10 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
count++;
|
||||
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
int16_t *csi_rs_ls_estimated_channel16 = (int16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][k];
|
||||
int16_t *csi_rs_estimated_channel16 = (int16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k];
|
||||
int16_t *csi_rs_estimated_channel16 = (int16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k_offset];
|
||||
if( (k == 0) || (k == frame_parms->first_carrier_offset) ) { // Start of OFDM symbol case or first occupied subcarrier case
|
||||
multadd_real_vector_complex_scalar(filt24_start, csi_rs_ls_estimated_channel16, csi_rs_estimated_channel16, 24);
|
||||
} else if( ( (k + NR_NB_SC_PER_RB) >= frame_parms->ofdm_symbol_size) ||
|
||||
@@ -411,9 +416,10 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][k];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][k_offset];
|
||||
noise_real[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel16->r-csi_rs_estimated_channel16->r);
|
||||
noise_imag[ant_rx][port_tx][rb-csirs_config_pdu->start_rb] = abs(csi_rs_ls_estimated_channel16->i-csi_rs_estimated_channel16->i);
|
||||
maxh = cmax3(maxh, abs(csi_rs_estimated_channel16->r), abs(csi_rs_estimated_channel16->i));
|
||||
@@ -431,7 +437,7 @@ int nr_csi_rs_channel_estimation(const PHY_VARS_NR_UE *ue,
|
||||
LOG_I(NR_PHY, "(k = %4d) |\t", k);
|
||||
for(uint16_t port_tx = 0; port_tx<N_ports; port_tx++) {
|
||||
c16_t *csi_rs_ls_estimated_channel16 = (c16_t*)&csi_rs_ls_estimated_channel[ant_rx][port_tx][0];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][0];
|
||||
c16_t *csi_rs_estimated_channel16 = (c16_t *)&csi_rs_estimated_channel_freq[ant_rx][port_tx][mem_offset];
|
||||
printf("Channel port_tx %d --> ant_rx %d : ls (%4d,%4d), int (%4d,%4d), noise (%4d,%4d) | ",
|
||||
port_tx+3000, ant_rx,
|
||||
csi_rs_ls_estimated_channel16[k].r, csi_rs_ls_estimated_channel16[k].i,
|
||||
@@ -460,7 +466,8 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const uint8_t N_ports,
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
uint8_t mem_offset,
|
||||
int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
const int16_t log2_maxh,
|
||||
uint8_t *rank_indicator) {
|
||||
|
||||
@@ -482,12 +489,11 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
* | conjch01 conjch11 | | ch10 ch11 | | conjch01*ch00+conjch11*ch10 conjch01*ch01+conjch11*ch11 |
|
||||
*/
|
||||
|
||||
int32_t csi_rs_estimated_conjch_ch[frame_parms->nb_antennas_rx][N_ports][frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_A_MF[N_ports][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_A_MF_sq[N_ports][N_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_determ_fin[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_numer_fin[frame_parms->ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
|
||||
int32_t csi_rs_estimated_conjch_ch[frame_parms->nb_antennas_rx][N_ports][frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_A_MF[N_ports][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_A_MF_sq[N_ports][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_determ_fin[frame_parms->ofdm_symbol_size + FILTER_MARGIN] __attribute__((aligned(32)));
|
||||
int32_t csi_rs_estimated_numer_fin[frame_parms->ofdm_symbol_size + FILTER_MARGIN] __attribute__((aligned(32)));
|
||||
const uint8_t sum_shift = 1; // log2(2x2) = 2, which is a shift of 1 bit
|
||||
|
||||
for (int rb = csirs_config_pdu->start_rb; rb < (csirs_config_pdu->start_rb+csirs_config_pdu->nr_of_rbs); rb++) {
|
||||
@@ -496,6 +502,7 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb*NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
|
||||
for (int ant_rx_conjch = 0; ant_rx_conjch < frame_parms->nb_antennas_rx; ant_rx_conjch++) {
|
||||
for(uint16_t port_tx_conjch = 0; port_tx_conjch < N_ports; port_tx_conjch++) {
|
||||
@@ -503,16 +510,16 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
for(uint16_t port_tx_ch = 0; port_tx_ch < N_ports; port_tx_ch++) {
|
||||
|
||||
// conjch x ch computation
|
||||
nr_conjch0_mult_ch1(&csi_rs_estimated_channel_freq[ant_rx_conjch][port_tx_conjch][k],
|
||||
&csi_rs_estimated_channel_freq[ant_rx_ch][port_tx_ch][k],
|
||||
&csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k],
|
||||
nr_conjch0_mult_ch1(&csi_rs_estimated_channel_freq[ant_rx_conjch][port_tx_conjch][k_offset],
|
||||
&csi_rs_estimated_channel_freq[ant_rx_ch][port_tx_ch][k_offset],
|
||||
&csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k_offset],
|
||||
1,
|
||||
log2_maxh);
|
||||
|
||||
// construct Hh x H elements
|
||||
if(ant_rx_conjch == ant_rx_ch) {
|
||||
nr_a_sum_b((__m128i *)&csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k],
|
||||
(__m128i *)&csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k],
|
||||
nr_a_sum_b((__m128i *)&csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k_offset],
|
||||
(__m128i *)&csi_rs_estimated_conjch_ch[ant_rx_conjch][port_tx_conjch][ant_rx_ch][port_tx_ch][k_offset],
|
||||
1);
|
||||
}
|
||||
}
|
||||
@@ -521,44 +528,44 @@ int nr_csi_rs_ri_estimation(const PHY_VARS_NR_UE *ue,
|
||||
}
|
||||
|
||||
// compute the determinant of A_MF (denominator)
|
||||
nr_det_A_MF_2x2(&csi_rs_estimated_A_MF[0][0][k],
|
||||
&csi_rs_estimated_A_MF[0][1][k],
|
||||
&csi_rs_estimated_A_MF[1][0][k],
|
||||
&csi_rs_estimated_A_MF[1][1][k],
|
||||
&csi_rs_estimated_determ_fin[k],
|
||||
nr_det_A_MF_2x2(&csi_rs_estimated_A_MF[0][0][k_offset],
|
||||
&csi_rs_estimated_A_MF[0][1][k_offset],
|
||||
&csi_rs_estimated_A_MF[1][0][k_offset],
|
||||
&csi_rs_estimated_A_MF[1][1][k_offset],
|
||||
&csi_rs_estimated_determ_fin[k_offset],
|
||||
1);
|
||||
|
||||
// compute the square of A_MF (numerator)
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][0][k], &csi_rs_estimated_A_MF_sq[0][0][k], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][1][k], &csi_rs_estimated_A_MF_sq[0][1][k], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][0][k], &csi_rs_estimated_A_MF_sq[1][0][k], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][1][k], &csi_rs_estimated_A_MF_sq[1][1][k], 1);
|
||||
nr_numer_2x2(&csi_rs_estimated_A_MF_sq[0][0][k],
|
||||
&csi_rs_estimated_A_MF_sq[0][1][k],
|
||||
&csi_rs_estimated_A_MF_sq[1][0][k],
|
||||
&csi_rs_estimated_A_MF_sq[1][1][k],
|
||||
&csi_rs_estimated_numer_fin[k],
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][0][k_offset], &csi_rs_estimated_A_MF_sq[0][0][k_offset], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[0][1][k_offset], &csi_rs_estimated_A_MF_sq[0][1][k_offset], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][0][k_offset], &csi_rs_estimated_A_MF_sq[1][0][k_offset], 1);
|
||||
nr_squared_matrix_element(&csi_rs_estimated_A_MF[1][1][k_offset], &csi_rs_estimated_A_MF_sq[1][1][k_offset], 1);
|
||||
nr_numer_2x2(&csi_rs_estimated_A_MF_sq[0][0][k_offset],
|
||||
&csi_rs_estimated_A_MF_sq[0][1][k_offset],
|
||||
&csi_rs_estimated_A_MF_sq[1][0][k_offset],
|
||||
&csi_rs_estimated_A_MF_sq[1][1][k_offset],
|
||||
&csi_rs_estimated_numer_fin[k_offset],
|
||||
1);
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
for(uint16_t port_tx_conjch = 0; port_tx_conjch < N_ports; port_tx_conjch++) {
|
||||
for(uint16_t port_tx_ch = 0; port_tx_ch < N_ports; port_tx_ch++) {
|
||||
c16_t *csi_rs_estimated_A_MF_k = (c16_t *) &csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k];
|
||||
c16_t *csi_rs_estimated_A_MF_k = (c16_t *) &csi_rs_estimated_A_MF[port_tx_conjch][port_tx_ch][k_offset];
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_A_MF[%i][%i] = (%i, %i)\n",
|
||||
k, port_tx_conjch, port_tx_ch, csi_rs_estimated_A_MF_k->r, csi_rs_estimated_A_MF_k->i);
|
||||
c16_t *csi_rs_estimated_A_MF_sq_k = (c16_t *) &csi_rs_estimated_A_MF_sq[port_tx_conjch][port_tx_ch][k];
|
||||
c16_t *csi_rs_estimated_A_MF_sq_k = (c16_t *) &csi_rs_estimated_A_MF_sq[port_tx_conjch][port_tx_ch][k_offset];
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_A_MF_sq[%i][%i] = (%i, %i)\n",
|
||||
k, port_tx_conjch, port_tx_ch, csi_rs_estimated_A_MF_sq_k->r, csi_rs_estimated_A_MF_sq_k->i);
|
||||
}
|
||||
}
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_determ_fin = %i\n", k, csi_rs_estimated_determ_fin[k]);
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_numer_fin = %i\n", k, csi_rs_estimated_numer_fin[k]>>sum_shift);
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_determ_fin = %i\n", k, csi_rs_estimated_determ_fin[k_offset]);
|
||||
LOG_I(NR_PHY, "(%i) csi_rs_estimated_numer_fin = %i\n", k, csi_rs_estimated_numer_fin[k_offset]>>sum_shift);
|
||||
#endif
|
||||
|
||||
// compute the conditional number
|
||||
for (int sc_idx=0; sc_idx < NR_NB_SC_PER_RB; sc_idx++) {
|
||||
int8_t csi_rs_estimated_denum_db = dB_fixed(csi_rs_estimated_determ_fin[k + sc_idx]);
|
||||
int8_t csi_rs_estimated_numer_db = dB_fixed(csi_rs_estimated_numer_fin[k + sc_idx]>>sum_shift);
|
||||
int8_t csi_rs_estimated_denum_db = dB_fixed(csi_rs_estimated_determ_fin[k_offset + sc_idx]);
|
||||
int8_t csi_rs_estimated_numer_db = dB_fixed(csi_rs_estimated_numer_fin[k_offset + sc_idx]>>sum_shift);
|
||||
int8_t cond_db = csi_rs_estimated_numer_db - csi_rs_estimated_denum_db;
|
||||
|
||||
#ifdef NR_CSIRS_DEBUG
|
||||
@@ -592,7 +599,8 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
|
||||
const fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu,
|
||||
const nr_csi_info_t *nr_csi_info,
|
||||
const uint8_t N_ports,
|
||||
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size],
|
||||
uint8_t mem_offset,
|
||||
const int32_t csi_rs_estimated_channel_freq[][N_ports][ue->frame_parms.ofdm_symbol_size + FILTER_MARGIN],
|
||||
const uint32_t interference_plus_noise_power,
|
||||
const uint8_t rank_indicator,
|
||||
const int16_t log2_re,
|
||||
@@ -631,11 +639,10 @@ int nr_csi_rs_pmi_estimation(const PHY_VARS_NR_UE *ue,
|
||||
continue;
|
||||
}
|
||||
uint16_t k = (frame_parms->first_carrier_offset + rb * NR_NB_SC_PER_RB) % frame_parms->ofdm_symbol_size;
|
||||
|
||||
uint16_t k_offset = k + mem_offset;
|
||||
for (int ant_rx = 0; ant_rx < frame_parms->nb_antennas_rx; ant_rx++) {
|
||||
|
||||
c16_t *csi_rs_estimated_channel_p0 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][0][k];
|
||||
c16_t *csi_rs_estimated_channel_p1 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][1][k];
|
||||
c16_t *csi_rs_estimated_channel_p0 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][0][k_offset];
|
||||
c16_t *csi_rs_estimated_channel_p1 = (c16_t *) &csi_rs_estimated_channel_freq[ant_rx][1][k_offset];
|
||||
|
||||
// H_p0 + 1*H_p1 = (H_p0_re + H_p1_re) + 1j*(H_p0_im + H_p1_im)
|
||||
sum_re[0] += (csi_rs_estimated_channel_p0->r+csi_rs_estimated_channel_p1->r);
|
||||
@@ -773,9 +780,12 @@ int nr_csi_im_power_estimation(const PHY_VARS_NR_UE *ue,
|
||||
for (int sc_idx = 0; sc_idx<4; sc_idx++) {
|
||||
|
||||
uint16_t sc = sc0_offset + csiim_config_pdu->k_csiim[sc_idx];
|
||||
if (sc >= frame_parms->ofdm_symbol_size) {
|
||||
sc -= frame_parms->ofdm_symbol_size;
|
||||
}
|
||||
|
||||
#ifdef NR_CSIIM_DEBUG
|
||||
LOG_I(NR_PHY, "(ant_rx %i, sc %i) real %i, imag %i\n", ant_rx, rb, rx_signal[sc].r, rx_signal[sc].i);
|
||||
LOG_I(NR_PHY, "(ant_rx %i, sc %i) real %i, imag %i\n", ant_rx, sc, rx_signal[sc].r, rx_signal[sc].i);
|
||||
#endif
|
||||
|
||||
sum_re += rx_signal[sc].r;
|
||||
@@ -888,7 +898,12 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
l_overline);
|
||||
|
||||
int32_t csi_rs_ls_estimated_channel[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size];
|
||||
int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size];
|
||||
int32_t csi_rs_estimated_channel_freq[frame_parms->nb_antennas_rx][N_ports][frame_parms->ofdm_symbol_size + FILTER_MARGIN];
|
||||
|
||||
// (long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset] & 0x1F gives us the remainder of the integer division by 32 of the memory address
|
||||
// By subtracting the previous value of 32, we know how much is left to have a multiple of 32.
|
||||
// Doing >> 2 <=> /sizeof(int32_t), we know what is the index offset of the array.
|
||||
uint8_t mem_offset = (((32 - ((long)&csi_rs_estimated_channel_freq[0][0][frame_parms->first_carrier_offset])) & 0x1F) >> 2);
|
||||
|
||||
nr_get_csi_rs_signal(ue,
|
||||
proc,
|
||||
@@ -920,6 +935,7 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
j_cdm,
|
||||
k_overline,
|
||||
l_overline,
|
||||
mem_offset,
|
||||
csi_rs_ls_estimated_channel,
|
||||
csi_rs_estimated_channel_freq,
|
||||
&log2_re,
|
||||
@@ -930,6 +946,7 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
log2_maxh,
|
||||
&rank_indicator);
|
||||
@@ -938,6 +955,7 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
|
||||
csirs_config_pdu,
|
||||
ue->nr_csi_info,
|
||||
N_ports,
|
||||
mem_offset,
|
||||
csi_rs_estimated_channel_freq,
|
||||
ue->nr_csi_info->csi_im_meas_computed ? ue->nr_csi_info->interference_plus_noise_power : noise_power,
|
||||
rank_indicator,
|
||||
|
||||
@@ -686,7 +686,7 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
|
||||
get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset);
|
||||
|
||||
// Pointers to extracted PDCCH symbols in frequency-domain.
|
||||
int32_t rx_size = 4*n_rb*12;
|
||||
int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5;
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size];
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_comp[frame_parms->nb_antennas_rx][rx_size];
|
||||
__attribute__ ((aligned(32))) int32_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size];
|
||||
|
||||
@@ -283,6 +283,7 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
nr_dlsch_extract_rbs(ue->frame_parms.samples_per_slot_wCP,
|
||||
rxdataF,
|
||||
rx_size,
|
||||
pdsch_est_size,
|
||||
dl_ch_estimates,
|
||||
rxdataF_ext,
|
||||
dl_ch_estimates_ext,
|
||||
@@ -1599,8 +1600,9 @@ void nr_dlsch_channel_level_median(uint32_t rx_size,
|
||||
|
||||
void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
|
||||
c16_t rxdataF[][rxdataF_sz],
|
||||
uint32_t rx_size,
|
||||
int32_t dl_ch_estimates[][rx_size],
|
||||
const uint32_t rx_size,
|
||||
const uint32_t pdsch_est_size,
|
||||
int32_t dl_ch_estimates[][pdsch_est_size],
|
||||
int32_t rxdataF_ext[][rx_size],
|
||||
int32_t dl_ch_estimates_ext[][rx_size],
|
||||
unsigned char symbol,
|
||||
|
||||
@@ -545,8 +545,9 @@ void nr_dlsch_256qam_llr(NR_DL_FRAME_PARMS *frame_parms,
|
||||
*/
|
||||
void nr_dlsch_extract_rbs(uint32_t rxdataF_sz,
|
||||
c16_t rxdataF[][rxdataF_sz],
|
||||
uint32_t rx_size,
|
||||
int32_t dl_ch_estimates[][rx_size],
|
||||
const uint32_t rx_size,
|
||||
const uint32_t pdsch_est_size,
|
||||
int32_t dl_ch_estimates[][pdsch_est_size],
|
||||
int32_t rxdataF_ext[][rx_size],
|
||||
int32_t dl_ch_estimates_ext[][rx_size],
|
||||
unsigned char symbol,
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
#include <radio/COMMON/common_lib.h>
|
||||
#include <executables/softmodem-common.h>
|
||||
#include <openair1/PHY/TOOLS/calibration_scope.h>
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
|
||||
|
||||
volatile int oai_exit=false;
|
||||
int oai_exit=false;
|
||||
unsigned int mmapped_dma=0;
|
||||
int single_thread_flag;
|
||||
uint32_t timing_advance;
|
||||
@@ -21,6 +22,9 @@ uint64_t dlsch_slot_bitmap = (1<<1);
|
||||
uint64_t ulsch_slot_bitmap = (1<<8);
|
||||
uint32_t target_ul_bw = 50;
|
||||
uint32_t target_dl_bw = 50;
|
||||
uint32_t target_dl_Nl;
|
||||
uint32_t target_ul_Nl;
|
||||
char *uecap_file;
|
||||
#include <executables/nr-softmodem.h>
|
||||
|
||||
int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {return 0;}
|
||||
|
||||
@@ -579,8 +579,8 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
ue->Mod_id,nr_slot_rx,harq_pid,dlsch0_harq->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->dlsch_config.dlDmrsSymbPos, dlsch0->Nl);
|
||||
|
||||
const uint32_t pdsch_est_size = ((ue->frame_parms.symbols_per_slot*ue->frame_parms.ofdm_symbol_size+15)/16)*16;
|
||||
__attribute__ ((aligned(32))) int32_t pdsch_dl_ch_estimates[ue->frame_parms.nb_antennas_rx][pdsch_est_size];
|
||||
memset(pdsch_dl_ch_estimates, 0, sizeof(int32_t)*ue->frame_parms.nb_antennas_rx*pdsch_est_size);
|
||||
__attribute__ ((aligned(32))) int32_t pdsch_dl_ch_estimates[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][pdsch_est_size];
|
||||
memset(pdsch_dl_ch_estimates, 0, sizeof(int32_t)*ue->frame_parms.nb_antennas_rx*dlsch0->Nl*pdsch_est_size);
|
||||
|
||||
for (m = s0; m < (s0 +s1); m++) {
|
||||
if (dlsch0->dlsch_config.dlDmrsSymbPos & (1 << m)) {
|
||||
@@ -645,26 +645,25 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
uint32_t dl_valid_re[NR_SYMBOLS_PER_SLOT] = {0};
|
||||
uint32_t llr_offset[NR_SYMBOLS_PER_SLOT] = {0};
|
||||
|
||||
const uint32_t rx_size = NR_SYMBOLS_PER_SLOT*
|
||||
dlsch[0].dlsch_config.number_rbs*
|
||||
NR_NB_SC_PER_RB;
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_estimates_ext[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(dl_ch_estimates_ext, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
const uint32_t rx_size = ((NR_SYMBOLS_PER_SLOT * dlsch[0].dlsch_config.number_rbs * NR_NB_SC_PER_RB + 15) >> 4) << 4;
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_ext[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(rxdataF_ext, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_estimates_ext[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(dl_ch_estimates_ext, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_comp[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(rxdataF_comp, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_ext[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(rxdataF_ext, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_mag[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(dl_ch_mag, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
__attribute__ ((aligned(32))) int32_t rxdataF_comp[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(rxdataF_comp, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_magb[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(dl_ch_magb, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_mag[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(dl_ch_mag, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_magr[ue->frame_parms.nb_antennas_rx][rx_size];
|
||||
memset(dl_ch_magr, 0, ue->frame_parms.nb_antennas_rx*rx_size*sizeof(int32_t));
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_magb[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(dl_ch_magb, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
__attribute__ ((aligned(32))) int32_t dl_ch_magr[ue->frame_parms.nb_antennas_rx*dlsch0->Nl][rx_size];
|
||||
memset(dl_ch_magr, 0, ue->frame_parms.nb_antennas_rx*dlsch0->Nl*rx_size*sizeof(int32_t));
|
||||
|
||||
int32_t log2_maxh = 0;
|
||||
start_meas(&ue->rx_pdsch_stats);
|
||||
@@ -714,16 +713,16 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
|
||||
} // CRNTI active
|
||||
stop_meas(&ue->rx_pdsch_stats);
|
||||
|
||||
UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx, rx_size);
|
||||
UEscopeCopy(ue, pdschRxdataF_comp, rxdataF_comp, sizeof(struct complex16), ue->frame_parms.nb_antennas_rx*dlsch0->Nl, rx_size);
|
||||
|
||||
if (ue->phy_sim_pdsch_rxdataF_comp)
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_comp, rxdataF_comp, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_comp, rxdataF_comp, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx*dlsch0->Nl);
|
||||
if (ue->phy_sim_pdsch_rxdataF_ext)
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_ext, rxdataF_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_ext, rxdataF_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx*dlsch0->Nl);
|
||||
if (ue->phy_sim_pdsch_dl_ch_estimates_ext)
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx*dlsch0->Nl);
|
||||
if (ue->phy_sim_pdsch_dl_ch_estimates)
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx);
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates, dl_ch_estimates_ext, sizeof(int32_t)*rx_size*ue->frame_parms.nb_antennas_rx*dlsch0->Nl);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <signal.h>
|
||||
#include "common/config/config_load_configmodule.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/var_array.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
@@ -52,7 +53,6 @@
|
||||
#include "SCHED/sched_eNB.h"
|
||||
#include "SCHED_UE/sched_UE.h"
|
||||
#include "SIMULATION/TOOLS/sim.h"
|
||||
#include "UTIL/LISTS/list.h"
|
||||
#include "OCG_vars.h"
|
||||
#include "unitary_defs.h"
|
||||
#include "dummy_functions.c"
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include "common/utils/var_array.h"
|
||||
#include "PHY/types.h"
|
||||
#include "PHY/defs_common.h"
|
||||
#include "PHY/defs_eNB.h"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "common/ran_context.h"
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/var_array.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
|
||||
#include "LAYER2/NR_MAC_UE/mac_defs.h"
|
||||
@@ -81,7 +82,6 @@ const char *__asan_default_options()
|
||||
}
|
||||
|
||||
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
|
||||
rlc_info_t Rlc_info_um,Rlc_info_am_config;
|
||||
|
||||
PHY_VARS_gNB *gNB;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
@@ -1042,12 +1042,13 @@ int main(int argc, char **argv)
|
||||
memset(msgDataTx->ssb, 0, 64*sizeof(NR_gNB_SSB_t));
|
||||
|
||||
// Buffers to store internal memory of slot process
|
||||
UE->phy_sim_rxdataF = calloc(frame_parms->samples_per_slot_wCP*sizeof(int32_t), frame_parms->nb_antennas_rx);
|
||||
UE->phy_sim_pdsch_llr = calloc((8*(3*8*8448))*sizeof(int16_t), 1); //Max length
|
||||
UE->phy_sim_pdsch_rxdataF_ext = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
|
||||
UE->phy_sim_pdsch_rxdataF_comp = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
|
||||
UE->phy_sim_pdsch_dl_ch_estimates = calloc(14*frame_parms->ofdm_symbol_size*sizeof(int32_t), frame_parms->nb_antennas_rx);
|
||||
UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(14*frame_parms->N_RB_DL*12*sizeof(int32_t), frame_parms->nb_antennas_rx);
|
||||
int rx_size = (((14 * frame_parms->N_RB_DL * 12 * sizeof(int32_t)) + 15) >> 4) << 4;
|
||||
UE->phy_sim_rxdataF = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, frame_parms->samples_per_slot_wCP * sizeof(int32_t));
|
||||
UE->phy_sim_pdsch_llr = calloc(1, (8 * (3 * 8 * 8448)) * sizeof(int16_t)); // Max length
|
||||
UE->phy_sim_pdsch_rxdataF_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
|
||||
UE->phy_sim_pdsch_rxdataF_comp = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
|
||||
UE->phy_sim_pdsch_dl_ch_estimates = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
|
||||
UE->phy_sim_pdsch_dl_ch_estimates_ext = calloc(sizeof(int32_t *) * frame_parms->nb_antennas_rx * g_nrOfLayers, rx_size);
|
||||
|
||||
for (SNR = snr0; SNR < snr1; SNR += .2) {
|
||||
|
||||
|
||||
@@ -751,11 +751,12 @@ int main(int argc, char **argv)
|
||||
|
||||
UE->rx_offset=0;
|
||||
uint8_t ssb_index = 0;
|
||||
const int estimateSz=7*2*sizeof(int)*frame_parms->ofdm_symbol_size;
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][estimateSz];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++; // to select the first transmitted ssb
|
||||
UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms,ssb_index);
|
||||
const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size;
|
||||
__attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz];
|
||||
__attribute__((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size];
|
||||
while (!((SSB_positions >> ssb_index) & 0x01))
|
||||
ssb_index++; // to select the first transmitted ssb
|
||||
UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index);
|
||||
|
||||
int ssb_slot = (UE->symbol_offset/14)+(n_hf*(frame_parms->slots_per_frame>>1));
|
||||
proc.nr_slot_rx = ssb_slot;
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
#define PRACH_WRITE_OUTPUT_DEBUG 1
|
||||
|
||||
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
|
||||
rlc_info_t Rlc_info_um,Rlc_info_am_config;
|
||||
|
||||
char *uecap_file;
|
||||
PHY_VARS_gNB *gNB;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "common/config/config_userapi.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/nr/nr_common.h"
|
||||
#include "common/utils/var_array.h"
|
||||
#include "PHY/defs_gNB.h"
|
||||
#include "PHY/defs_nr_common.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
@@ -76,7 +77,6 @@ const char *__asan_default_options()
|
||||
}
|
||||
|
||||
LCHAN_DESC DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
|
||||
rlc_info_t Rlc_info_um,Rlc_info_am_config;
|
||||
|
||||
PHY_VARS_gNB *gNB;
|
||||
PHY_VARS_NR_UE *UE;
|
||||
|
||||
@@ -112,7 +112,7 @@ void RCconfig_L1(void) {
|
||||
// This is used by init_eNB_afterRU()
|
||||
RC.nb_CC = (int *)malloc((1+RC.nb_inst)*sizeof(int));
|
||||
RC.nb_CC[0]=1;
|
||||
RC.nb_inst =1; // DJP - feptx_prec uses num_eNB but phy_init_RU uses nb_inst
|
||||
RC.nb_inst =1; // feptx_prec uses num_eNB but phy_init_RU uses nb_inst
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_inst=1 this is because phy_init_RU() uses that to index and not RC.num_eNB - why the 2 similar variables?\n", __FUNCTION__);
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_CC[0]=%d for init_eNB_afterRU()\n", __FUNCTION__, RC.nb_CC[0]);
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_macrlc_inst:%d because used by mac_top_init_eNB()\n", __FUNCTION__, RC.nb_macrlc_inst);
|
||||
@@ -142,10 +142,10 @@ void RCconfig_L1(void) {
|
||||
l1_north_init_eNB();
|
||||
} else {
|
||||
LOG_I(PHY,"No " CONFIG_STRING_L1_LIST " configuration found");
|
||||
// DJP need to create some structures for VNF
|
||||
// need to create some structures for VNF
|
||||
j = 0;
|
||||
RC.nb_L1_CC = malloc((1+RC.nb_L1_inst)*sizeof(int)); // DJP - 1 lot then???
|
||||
RC.nb_L1_CC[j]=1; // DJP - hmmm
|
||||
RC.nb_L1_CC = malloc((1+RC.nb_L1_inst)*sizeof(int));
|
||||
RC.nb_L1_CC[j]=1;
|
||||
|
||||
if (RC.eNB[j] == NULL) {
|
||||
RC.eNB[j] = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB **));
|
||||
@@ -224,7 +224,7 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) {
|
||||
RC.mac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr);
|
||||
RC.mac[j]->eth_params_s.transp_preference = ETH_UDP_MODE;
|
||||
LOG_I(ENB_APP,"**************** vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc);
|
||||
configure_nfapi_vnf(RC.mac[j]->eth_params_s.my_addr, RC.mac[j]->eth_params_s.my_portc);
|
||||
configure_nfapi_vnf(RC.mac[j]->eth_params_s.my_addr, RC.mac[j]->eth_params_s.my_portc,RC.mac[j]->eth_params_s.remote_addr,RC.mac[j]->eth_params_s.remote_portd,RC.mac[j]->eth_params_s.my_portd);
|
||||
LOG_I(ENB_APP,"**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.mac[j]->eth_params_s.my_portc);
|
||||
} else { // other midhaul
|
||||
AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
||||
|
||||
+175
-167
@@ -86,6 +86,7 @@
|
||||
#include "RRC/NR/MESSAGES/asn1_msg.h"
|
||||
#include "RRC/NR/nr_rrc_extern.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h"
|
||||
#include "nfapi/oai_integration/vendor_ext.h"
|
||||
|
||||
extern uint16_t sf_ahead;
|
||||
int macrlc_has_f1 = 0;
|
||||
@@ -684,226 +685,234 @@ void RCconfig_nr_prs(void)
|
||||
}
|
||||
}
|
||||
|
||||
void RCconfig_NR_L1(void) {
|
||||
int j;
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
////////// Identification parameters
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
void RCconfig_NR_L1(void)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **)malloc((1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
|
||||
LOG_I(NR_PHY, "RC.gNB = %p\n", RC.gNB);
|
||||
memset(RC.gNB, 0, (1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
|
||||
|
||||
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = calloc(1, sizeof(PHY_VARS_gNB));
|
||||
}
|
||||
}
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
////////// Identification parameters
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
|
||||
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
||||
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
if (ulprbbl) LOG_I(NR_PHY,"PRB blacklist %s\n",ulprbbl);
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
int prbbl[275];
|
||||
int num_prbbl=0;
|
||||
memset(prbbl,0,275*sizeof(int));
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
|
||||
while (pt) {
|
||||
const int rb = atoi(pt);
|
||||
AssertFatal(rb < 275, "RB %d out of bounds (max 275)\n", rb);
|
||||
prbbl[rb] = 0x3FFF; // all symbols taken
|
||||
LOG_I(NR_PHY,"Blacklisting prb %d\n",atoi(pt));
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
|
||||
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
|
||||
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
|
||||
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
if (ulprbbl)
|
||||
LOG_I(NR_PHY, "PRB blacklist %s\n", ulprbbl);
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
int prbbl[275];
|
||||
int num_prbbl = 0;
|
||||
memset(prbbl, 0, 275 * sizeof(int));
|
||||
|
||||
while (pt) {
|
||||
const int rb = atoi(pt);
|
||||
AssertFatal(rb < 275, "RB %d out of bounds (max 275)\n", rb);
|
||||
prbbl[rb] = 0x3FFF; // all symbols taken
|
||||
LOG_I(NR_PHY, "Blacklisting prb %d\n", atoi(pt));
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
|
||||
RC.gNB[j]->num_ulprbbl = num_prbbl;
|
||||
LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_prbbl);
|
||||
memcpy(RC.gNB[j]->ulprbbl, prbbl, 275 * sizeof(int));
|
||||
|
||||
RC.gNB[j]->ap_N1 = N1;
|
||||
RC.gNB[j]->ap_N2 = N2;
|
||||
RC.gNB[j]->ap_XP = XP;
|
||||
}
|
||||
|
||||
paramdef_t L1_Params[] = L1PARAMS_DESC;
|
||||
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
|
||||
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST, NULL, 0};
|
||||
|
||||
|
||||
if (RC.gNB == NULL) {
|
||||
RC.gNB = (PHY_VARS_gNB **)malloc((1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
|
||||
LOG_I(NR_PHY,"RC.gNB = %p\n",RC.gNB);
|
||||
memset(RC.gNB,0,(1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
|
||||
}
|
||||
|
||||
config_getlist( &L1_ParamList,L1_Params,sizeof(L1_Params)/sizeof(paramdef_t), NULL);
|
||||
config_getlist(&L1_ParamList, L1_Params, sizeof(L1_Params) / sizeof(paramdef_t), NULL);
|
||||
|
||||
if (L1_ParamList.numelt > 0) {
|
||||
|
||||
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
|
||||
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
LOG_I(NR_PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]);
|
||||
memset(RC.gNB[j],0,sizeof(PHY_VARS_gNB));
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
LOG_I(NR_PHY, "RC.gNB[%d] = %p\n", j, RC.gNB[j]);
|
||||
memset(RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
}
|
||||
AssertFatal(*L1_ParamList.paramarray[j][L1_THREAD_POOL_SIZE].uptr == 2022,
|
||||
"thread_pool_size removed, please use --thread-pool\n");
|
||||
AssertFatal(*L1_ParamList.paramarray[j][L1_THREAD_POOL_SIZE].uptr == 2022, "thread_pool_size removed, please use --thread-pool\n");
|
||||
RC.gNB[j]->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr);
|
||||
RC.gNB[j]->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->srs_thres = *(L1_ParamList.paramarray[j][L1_SRS_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->srs_thres = *(L1_ParamList.paramarray[j][L1_SRS_DTX_THRESHOLD].uptr);
|
||||
RC.gNB[j]->max_ldpc_iterations = *(L1_ParamList.paramarray[j][L1_MAX_LDPC_ITERATIONS].uptr);
|
||||
RC.gNB[j]->num_ulprbbl = num_prbbl;
|
||||
RC.gNB[j]->ap_N1 = N1;
|
||||
RC.gNB[j]->ap_N2 = N2;
|
||||
RC.gNB[j]->ap_XP = XP;
|
||||
LOG_I(NR_PHY,"Copying %d blacklisted PRB to L1 context\n",num_prbbl);
|
||||
memcpy(RC.gNB[j]->ulprbbl,prbbl,275*sizeof(int));
|
||||
if(strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
|
||||
//sf_ahead = 2; // Need 4 subframe gap between RX and TX
|
||||
}else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
RC.gNB[j]->eth_params_n.local_if_name = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.my_addr = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.remote_addr = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
|
||||
// sf_ahead = 2; // Need 4 subframe gap between RX and TX
|
||||
} else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
RC.gNB[j]->eth_params_n.local_if_name = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.my_addr = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.remote_addr = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.gNB[j]->eth_params_n.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
|
||||
RC.gNB[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
|
||||
//sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
|
||||
// sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
|
||||
|
||||
RC.nb_nr_macrlc_inst = 1; // This is used by mac_top_init_gNB()
|
||||
RC.nb_nr_macrlc_inst = 1; // This is used by mac_top_init_gNB()
|
||||
|
||||
// This is used by init_gNB_afterRU()
|
||||
RC.nb_nr_CC = (int *)malloc((1+RC.nb_nr_inst)*sizeof(int));
|
||||
RC.nb_nr_CC[0]=1;
|
||||
RC.nb_nr_CC = (int *)malloc((1 + RC.nb_nr_inst) * sizeof(int));
|
||||
RC.nb_nr_CC[0] = 1;
|
||||
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_inst=1 this is because phy_init_RU() uses that to index and not RC.num_gNB - why the 2 similar variables?\n", __FUNCTION__);
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_CC[0]=%d for init_gNB_afterRU()\n", __FUNCTION__, RC.nb_nr_CC[0]);
|
||||
LOG_I(PHY,"%s() NFAPI PNF mode - RC.nb_nr_macrlc_inst:%d because used by mac_top_init_gNB()\n", __FUNCTION__, RC.nb_nr_macrlc_inst);
|
||||
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_inst=1 this is because phy_init_RU() uses that to index and not RC.num_gNB - why the 2 similar variables?\n", __FUNCTION__);
|
||||
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_CC[0]=%d for init_gNB_afterRU()\n", __FUNCTION__, RC.nb_nr_CC[0]);
|
||||
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_macrlc_inst:%d because used by mac_top_init_gNB()\n", __FUNCTION__, RC.nb_nr_macrlc_inst);
|
||||
|
||||
configure_nr_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr,
|
||||
RC.gNB[j]->eth_params_n.remote_portc,
|
||||
RC.gNB[j]->eth_params_n.my_addr,
|
||||
RC.gNB[j]->eth_params_n.my_portd,
|
||||
RC.gNB[j]->eth_params_n.remote_portd);
|
||||
}else { // other midhaul
|
||||
}
|
||||
}// for (j = 0; j < RC.nb_nr_L1_inst; j++)
|
||||
} else { // other midhaul
|
||||
}
|
||||
} // for (j = 0; j < RC.nb_nr_L1_inst; j++)
|
||||
printf("Initializing northbound interface for L1\n");
|
||||
l1_north_init_gNB();
|
||||
}else{
|
||||
LOG_I(PHY,"No " CONFIG_STRING_L1_LIST " configuration found");
|
||||
} else {
|
||||
LOG_I(PHY, "No " CONFIG_STRING_L1_LIST " configuration found");
|
||||
|
||||
// DJP need to create some structures for VNF
|
||||
// need to create some structures for VNF
|
||||
|
||||
j = 0;
|
||||
|
||||
|
||||
if (RC.gNB[j] == NULL) {
|
||||
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
|
||||
memset((void*)RC.gNB[j],0,sizeof(PHY_VARS_gNB));
|
||||
LOG_I(PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]);
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
}
|
||||
memset((void *)RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
|
||||
LOG_I(PHY, "RC.gNB[%d] = %p\n", j, RC.gNB[j]);
|
||||
RC.gNB[j]->Mod_id = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RCconfig_nr_macrlc() {
|
||||
int j;
|
||||
int j = 0;
|
||||
uint16_t prbbl[275] = {0};
|
||||
int num_prbbl = 0;
|
||||
if (NFAPI_MODE != NFAPI_MODE_PNF) {
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
////////// Identification parameters
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
|
||||
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
||||
////////// Identification parameters
|
||||
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
||||
|
||||
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
|
||||
ngran_node_t node_type = get_node_type();
|
||||
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
|
||||
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
||||
AssertFatal (num_gnbs > 0,"Failed to parse config file no gnbs %s \n",GNB_CONFIG_STRING_ACTIVE_GNBS);
|
||||
|
||||
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
uint16_t prbbl[275];
|
||||
int num_prbbl=0;
|
||||
memset(prbbl,0,sizeof(prbbl));
|
||||
while (pt) {
|
||||
const int prb = atoi(pt);
|
||||
AssertFatal(prb < 275, "RB %d out of bounds (max 275)\n", prb);
|
||||
prbbl[prb] = 0x3FFF; // all symbols taken
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
|
||||
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
|
||||
char *save = NULL;
|
||||
char *pt = strtok_r(ulprbbl, ",", &save);
|
||||
memset(prbbl, 0, sizeof(prbbl));
|
||||
while (pt) {
|
||||
const int prb = atoi(pt);
|
||||
AssertFatal(prb < 275, "RB %d out of bounds (max 275)\n", prb);
|
||||
prbbl[prb] = 0x3FFF; // all symbols taken
|
||||
pt = strtok_r(NULL, ",", &save);
|
||||
num_prbbl++;
|
||||
}
|
||||
}
|
||||
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
|
||||
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
|
||||
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0};
|
||||
/* map parameter checking array instances to parameter definition array instances */
|
||||
checkedparam_t config_check_MacRLCParams [] = MACRLCPARAMS_CHECK;
|
||||
checkedparam_t config_check_MacRLCParams[] = MACRLCPARAMS_CHECK;
|
||||
for (int i = 0; i < sizeof(MacRLC_Params) / sizeof(paramdef_t); ++i)
|
||||
MacRLC_Params[i].chkPptr = &(config_check_MacRLCParams[i]);
|
||||
config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);
|
||||
|
||||
if ( MacRLC_ParamList.numelt > 0) {
|
||||
config_getlist(&MacRLC_ParamList, MacRLC_Params, sizeof(MacRLC_Params) / sizeof(paramdef_t), NULL);
|
||||
|
||||
RC.nb_nr_macrlc_inst=MacRLC_ParamList.numelt;
|
||||
if (MacRLC_ParamList.numelt > 0) {
|
||||
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
|
||||
ngran_node_t node_type = get_node_type();
|
||||
mac_top_init_gNB(node_type);
|
||||
RC.nb_nr_mac_CC = (int*)malloc(RC.nb_nr_macrlc_inst*sizeof(int));
|
||||
RC.nb_nr_mac_CC = (int *)malloc(RC.nb_nr_macrlc_inst * sizeof(int));
|
||||
|
||||
for (j=0;j<RC.nb_nr_macrlc_inst;j++) {
|
||||
for (j = 0; j < RC.nb_nr_macrlc_inst; j++) {
|
||||
RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr);
|
||||
RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr);
|
||||
RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr);
|
||||
RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr);
|
||||
RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr);
|
||||
RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr);
|
||||
|
||||
LOG_I(NR_MAC,"PUSCH Target %d, PUCCH Target %d, PUCCH Failure %d, PUSCH Failure %d\n",
|
||||
RC.nrmac[j]->pusch_target_snrx10,
|
||||
RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr);
|
||||
RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr);
|
||||
RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr);
|
||||
RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr);
|
||||
RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr);
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"PUSCH Target %d, PUCCH Target %d, PUCCH Failure %d, PUSCH Failure %d\n",
|
||||
RC.nrmac[j]->pusch_target_snrx10,
|
||||
RC.nrmac[j]->pucch_target_snrx10,
|
||||
RC.nrmac[j]->pucch_failure_thres,
|
||||
RC.nrmac[j]->pusch_failure_thres);
|
||||
RC.nrmac[j]->pusch_failure_thres);
|
||||
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) {
|
||||
// check number of instances is same as RRC/PDCP
|
||||
|
||||
}else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
|
||||
// check number of instances is same as RRC/PDCP
|
||||
|
||||
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
|
||||
printf("Configuring F1 interfaces for MACRLC\n");
|
||||
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);;
|
||||
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
macrlc_has_f1 = 1;
|
||||
}else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) {
|
||||
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);;
|
||||
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
}else { // other midhaul
|
||||
AssertFatal(1==0,"MACRLC %d: %s unknown northbound midhaul\n",j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr));
|
||||
}
|
||||
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);
|
||||
;
|
||||
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
macrlc_has_f1 = 1;
|
||||
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) {
|
||||
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);
|
||||
;
|
||||
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
|
||||
} else { // other midhaul
|
||||
AssertFatal(1 == 0, "MACRLC %d: %s unknown northbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr));
|
||||
}
|
||||
|
||||
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_L1") == 0) {
|
||||
|
||||
}else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
RC.nrmac[j]->eth_params_s.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE;
|
||||
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "nfapi") == 0) {
|
||||
RC.nrmac[j]->eth_params_s.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_IF_NAME_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_ADDRESS_IDX].strptr));
|
||||
RC.nrmac[j]->eth_params_s.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTC_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr);
|
||||
RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE;
|
||||
|
||||
printf("**************** vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc);
|
||||
configure_nr_nfapi_vnf(RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc);
|
||||
configure_nr_nfapi_vnf(
|
||||
RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc, RC.nrmac[j]->eth_params_s.remote_addr, RC.nrmac[j]->eth_params_s.remote_portd, RC.nrmac[j]->eth_params_s.my_portd);
|
||||
printf("**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc);
|
||||
}else { // other midhaul
|
||||
AssertFatal(1==0,"MACRLC %d: %s unknown southbound midhaul\n",j,*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
||||
}
|
||||
} else { // other midhaul
|
||||
AssertFatal(1 == 0, "MACRLC %d: %s unknown southbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
||||
}
|
||||
RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr);
|
||||
NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler;
|
||||
dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr);
|
||||
@@ -918,13 +927,12 @@ void RCconfig_nr_macrlc() {
|
||||
RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr);
|
||||
RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr);
|
||||
RC.nrmac[j]->num_ulprbbl = num_prbbl;
|
||||
memcpy(RC.nrmac[j]->ulprbbl,prbbl,275*sizeof(prbbl[0]));
|
||||
}// for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||
}else {// MacRLC_ParamList.numelt > 0
|
||||
LOG_E(PHY,"No %s configuration found\n", CONFIG_STRING_MACRLC_LIST);
|
||||
// AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found");
|
||||
memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0]));
|
||||
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
||||
} else { // MacRLC_ParamList.numelt > 0
|
||||
LOG_E(PHY, "No %s configuration found\n", CONFIG_STRING_MACRLC_LIST);
|
||||
// AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void config_security(gNB_RRC_INST *rrc)
|
||||
|
||||
@@ -3645,7 +3645,14 @@ int is_nr_UL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, sl
|
||||
else return(slot_in_period >= slots1+tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots ? 1 : 0);
|
||||
}
|
||||
|
||||
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols, int startSymbol, mappingType_t mappingtype, int length) {
|
||||
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
|
||||
int dci_format,
|
||||
int dmrs_TypeA_Position,
|
||||
int NrOfSymbols,
|
||||
int startSymbol,
|
||||
mappingType_t mappingtype,
|
||||
int length)
|
||||
{
|
||||
|
||||
int dmrs_AdditionalPosition = 0;
|
||||
NR_DMRS_DownlinkConfig_t *dmrs_config = NULL;
|
||||
@@ -3654,8 +3661,8 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
|
||||
|
||||
int l0 = 0; // type B
|
||||
if (mappingtype == typeA) {
|
||||
if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0=2;
|
||||
else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0=3;
|
||||
if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2) l0 = 2;
|
||||
else if (dmrs_TypeA_Position == NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3) l0 = 3;
|
||||
else AssertFatal(1==0,"Illegal dmrs_TypeA_Position %d\n",(int)dmrs_TypeA_Position);
|
||||
}
|
||||
// in case of DCI FORMAT 1_0 or dedicated pdsch config not received additionposition = pos2, len1 should be used
|
||||
@@ -3664,7 +3671,8 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
|
||||
|
||||
if (pdsch_Config != NULL) {
|
||||
if (mappingtype == typeA) { // Type A
|
||||
if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup)
|
||||
if (dci_format != NR_DL_DCI_FORMAT_1_0 &&
|
||||
pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup)
|
||||
dmrs_config = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
|
||||
} else if (mappingtype == typeB) {
|
||||
if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB && pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->present == NR_SetupRelease_DMRS_DownlinkConfig_PR_setup)
|
||||
@@ -3673,10 +3681,9 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
|
||||
AssertFatal(1==0,"Incorrect Mappingtype\n");
|
||||
}
|
||||
|
||||
AssertFatal(dmrs_config != NULL," DMRS configs not present in PDSCH DMRS Downlink config\n");
|
||||
|
||||
// default values of additionalposition is pos2
|
||||
if (dmrs_config->dmrs_AdditionalPosition != NULL) dmrs_AdditionalPosition = *dmrs_config->dmrs_AdditionalPosition;
|
||||
if (dmrs_config && dmrs_config->dmrs_AdditionalPosition != NULL)
|
||||
dmrs_AdditionalPosition = *dmrs_config->dmrs_AdditionalPosition;
|
||||
}
|
||||
|
||||
uint8_t ld, row, column;
|
||||
@@ -3727,12 +3734,36 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Posi
|
||||
return l_prime;
|
||||
}
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type)
|
||||
{
|
||||
|
||||
// Set downlink MCS table (Semi-persistent scheduling ignored for now)
|
||||
uint8_t mcsTableIdx = 0; // default value
|
||||
if (mcs_Table &&
|
||||
*mcs_Table == NR_PDSCH_Config__mcs_Table_qam256 &&
|
||||
dci_format == NR_DL_DCI_FORMAT_1_1 &&
|
||||
rnti_type == NR_RNTI_C)
|
||||
mcsTableIdx = 1;
|
||||
else if (rnti_type != NR_RNTI_MCS_C &&
|
||||
mcs_Table &&
|
||||
*mcs_Table == NR_PDSCH_Config__mcs_Table_qam64LowSE &&
|
||||
ss_type == NR_SearchSpace__searchSpaceType_PR_ue_Specific)
|
||||
mcsTableIdx = 2;
|
||||
else if (rnti_type == NR_RNTI_MCS_C)
|
||||
mcsTableIdx = 2;
|
||||
|
||||
LOG_D(NR_MAC,"DL MCS Table Index: %d\n", mcsTableIdx);
|
||||
return mcsTableIdx;
|
||||
|
||||
}
|
||||
|
||||
uint8_t get_pusch_mcs_table(long *mcs_Table,
|
||||
int is_tp,
|
||||
int dci_format,
|
||||
int rnti_type,
|
||||
int target_ss,
|
||||
bool config_grant) {
|
||||
bool config_grant)
|
||||
{
|
||||
|
||||
// implementing 6.1.4.1 in 38.214
|
||||
if (mcs_Table != NULL) {
|
||||
|
||||
@@ -61,7 +61,13 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn);
|
||||
|
||||
uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw);
|
||||
|
||||
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,int NrOfSymbols,int startSymbol,mappingType_t mappingtype,int length);
|
||||
int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config,
|
||||
int dci_format,
|
||||
int dmrs_TypeA_Position,
|
||||
int NrOfSymbols,
|
||||
int startSymbol,
|
||||
mappingType_t mappingtype,
|
||||
int length);
|
||||
|
||||
int is_nr_DL_slot(NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon,slot_t slotP);
|
||||
|
||||
@@ -151,6 +157,8 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
|
||||
|
||||
int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder);
|
||||
|
||||
uint8_t get_pdsch_mcs_table(long *mcs_Table, int dci_format, int rnti_type, int ss_type);
|
||||
|
||||
int get_format0(uint8_t index, uint8_t unpaired,frequency_range_t);
|
||||
|
||||
int64_t *get_prach_config_info(frequency_range_t freq_range,
|
||||
|
||||
@@ -897,6 +897,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config,
|
||||
NR_DL_DCI_FORMAT_1_0,
|
||||
(get_softmodem_params()->nsa) ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position,
|
||||
dlsch_config_pdu_1_0->number_symbols,
|
||||
dlsch_config_pdu_1_0->start_symbol,
|
||||
@@ -1306,6 +1307,7 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
|
||||
|
||||
/* dmrs symbol positions*/
|
||||
dlsch_config_pdu_1_1->dlDmrsSymbPos = fill_dmrs_mask(pdsch_Config,
|
||||
NR_DL_DCI_FORMAT_1_1,
|
||||
mac->scc? mac->scc->dmrs_TypeA_Position:mac->mib->dmrs_TypeA_Position,
|
||||
dlsch_config_pdu_1_1->number_symbols,
|
||||
dlsch_config_pdu_1_1->start_symbol,
|
||||
|
||||
@@ -539,7 +539,9 @@ void pf_dl(module_id_t module_id,
|
||||
NR_UE_info_t **UE_list,
|
||||
int max_num_ue,
|
||||
int n_rb_sched,
|
||||
uint16_t *rballoc_mask) {
|
||||
uint16_t *rballoc_mask)
|
||||
{
|
||||
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon;
|
||||
// UEs that could be scheduled
|
||||
@@ -748,7 +750,8 @@ void pf_dl(module_id_t module_id,
|
||||
}
|
||||
}
|
||||
|
||||
void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) {
|
||||
void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
|
||||
{
|
||||
NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info;
|
||||
|
||||
if (UE_info->list[0] == NULL)
|
||||
@@ -791,12 +794,17 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
|
||||
/* Retrieve amount of data to send for this UE */
|
||||
nr_store_dlsch_buffer(module_id, frame, slot);
|
||||
|
||||
int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
int average_agg_level = 4; // TODO find a better estimation
|
||||
int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_dl(module_id,
|
||||
frame,
|
||||
slot,
|
||||
UE_info->list,
|
||||
MAX_MOBILES_PER_GNB,
|
||||
max_sched_ues,
|
||||
n_rb_sched,
|
||||
rballoc_mask);
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
dmrs.dmrsConfigType = NFAPI_NR_DMRS_TYPE1;
|
||||
|
||||
dmrs.N_PRB_DMRS = dmrs.numDmrsCdmGrpsNoData * (dmrs.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4);
|
||||
dmrs.dl_dmrs_symb_pos = fill_dmrs_mask(pdsch_Config, scc->dmrs_TypeA_Position, tda_info->nrOfSymbols, tda_info->startSymbolIndex, tda_info->mapping_type, frontloaded_symb);
|
||||
dmrs.dl_dmrs_symb_pos = fill_dmrs_mask(pdsch_Config, dci_format, scc->dmrs_TypeA_Position, tda_info->nrOfSymbols, tda_info->startSymbolIndex, tda_info->mapping_type, frontloaded_symb);
|
||||
dmrs.N_DMRS_SLOT = get_num_dmrs(dmrs.dl_dmrs_symb_pos);
|
||||
LOG_D(NR_MAC,"Filling dmrs info, ps->N_PRB_DMRS %d, ps->dl_dmrs_symb_pos %x, ps->N_DMRS_SLOT %d\n",dmrs.N_PRB_DMRS,dmrs.dl_dmrs_symb_pos,dmrs.N_DMRS_SLOT);
|
||||
return dmrs;
|
||||
@@ -680,224 +680,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
|
||||
return new_mcs;
|
||||
}
|
||||
|
||||
void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
|
||||
nr_scs_e scs_common,
|
||||
nr_scs_e pdcch_scs,
|
||||
frequency_range_t freq_range,
|
||||
uint8_t rmsi_pdcch_config,
|
||||
uint8_t ssb_idx,
|
||||
uint8_t k_ssb,
|
||||
uint16_t sfn_ssb,
|
||||
uint8_t n_ssb, /*slot index overlapping the corresponding SSB index*/
|
||||
uint16_t nb_slots_per_frame,
|
||||
uint16_t N_RB)
|
||||
{
|
||||
// uint8_t O, M;
|
||||
// uint8_t ss_idx = rmsi_pdcch_config&0xf;
|
||||
// uint8_t cset_idx = (rmsi_pdcch_config>>4)&0xf;
|
||||
// uint8_t mu = scs_common;
|
||||
// uint8_t O_scale=0, M_scale=0; // used to decide if the values of O and M need to be divided by 2
|
||||
|
||||
AssertFatal(1==0,"todo\n");
|
||||
/*
|
||||
/// Coreset params
|
||||
switch(scs_common) {
|
||||
|
||||
case kHz15:
|
||||
|
||||
switch(pdcch_scs) {
|
||||
case kHz15:
|
||||
AssertFatal(cset_idx<15,"Coreset index %d reserved for scs kHz15/kHz15\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 6)? 24 : (cset_idx < 12)? 48 : 96;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_15[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
|
||||
break;
|
||||
|
||||
case kHz30:
|
||||
AssertFatal(cset_idx<14,"Coreset index %d reserved for scs kHz15/kHz30\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 8)? 24 : 48;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_15_30[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_15_15[cset_idx];
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case kHz30:
|
||||
|
||||
if (N_RB < 106) { // Minimum 40Mhz bandwidth not satisfied
|
||||
switch(pdcch_scs) {
|
||||
case kHz15:
|
||||
AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 10)? 48 : 96;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_b40Mhz[cset_idx];
|
||||
break;
|
||||
|
||||
case kHz30:
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 6)? 24 : 48;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_b40Mhz[cset_idx];
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||||
}
|
||||
}
|
||||
|
||||
else { // above 40Mhz
|
||||
switch(pdcch_scs) {
|
||||
case kHz15:
|
||||
AssertFatal(cset_idx<9,"Coreset index %d reserved for scs kHz30/kHz15\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 3)? 48 : 96;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_15_a40Mhz[cset_idx];
|
||||
break;
|
||||
|
||||
case kHz30:
|
||||
AssertFatal(cset_idx<10,"Coreset index %d reserved for scs kHz30/kHz30\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = (cset_idx < 4)? 24 : 48;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
|
||||
pdcch_pdu->rb_offset = nr_coreset_rb_offset_pdcch_type_0_scs_30_30_a40Mhz[cset_idx];
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kHz120:
|
||||
switch(pdcch_scs) {
|
||||
case kHz60:
|
||||
AssertFatal(cset_idx<12,"Coreset index %d reserved for scs kHz120/kHz60\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = (cset_idx < 8)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
|
||||
pdcch_pdu->n_rb = (cset_idx < 6)? 48 : (cset_idx < 8)? 96 : (cset_idx < 10)? 48 : 96;
|
||||
pdcch_pdu->n_symb = nr_coreset_nsymb_pdcch_type_0_scs_120_60[cset_idx];
|
||||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx]>0)?nr_coreset_rb_offset_pdcch_type_0_scs_120_60[cset_idx] :
|
||||
(k_ssb == 0)? -41 : -42;
|
||||
break;
|
||||
|
||||
case kHz120:
|
||||
AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz120/kHz120\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = (cset_idx < 4)?NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3;
|
||||
pdcch_pdu->n_rb = (cset_idx < 2)? 24 : (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
|
||||
pdcch_pdu->n_symb = (cset_idx == 2)? 1 : 2;
|
||||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_120_120[cset_idx] :
|
||||
(k_ssb == 0)? -20 : -21;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||||
}
|
||||
break;
|
||||
|
||||
case kHz240:
|
||||
switch(pdcch_scs) {
|
||||
case kHz60:
|
||||
AssertFatal(cset_idx<4,"Coreset index %d reserved for scs kHz240/kHz60\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1;
|
||||
pdcch_pdu->n_rb = 96;
|
||||
pdcch_pdu->n_symb = (cset_idx < 2)? 1 : 2;
|
||||
pdcch_pdu->rb_offset = (cset_idx&1)? 16 : 0;
|
||||
break;
|
||||
|
||||
case kHz120:
|
||||
AssertFatal(cset_idx<8,"Coreset index %d reserved for scs kHz240/kHz120\n", cset_idx);
|
||||
pdcch_pdu->mux_pattern = (cset_idx < 4)? NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1 : NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2;
|
||||
pdcch_pdu->n_rb = (cset_idx < 4)? 48 : (cset_idx < 6)? 24 : 48;
|
||||
pdcch_pdu->n_symb = ((cset_idx==2)||(cset_idx==3))? 2 : 1;
|
||||
pdcch_pdu->rb_offset = (nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx]>0)? nr_coreset_rb_offset_pdcch_type_0_scs_240_120[cset_idx] :
|
||||
(k_ssb == 0)? -41 : -42;
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid scs_common/pdcch_scs combination %d/%d \n", scs_common, pdcch_scs);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0,"Invalid common subcarrier spacing %d\n", scs_common);
|
||||
|
||||
}
|
||||
|
||||
/// Search space params
|
||||
switch(pdcch_pdu->mux_pattern) {
|
||||
|
||||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE1:
|
||||
if (freq_range == nr_FR1) {
|
||||
O = nr_ss_param_O_type_0_mux1_FR1[ss_idx];
|
||||
pdcch_pdu->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR1[ss_idx];
|
||||
M = nr_ss_param_M_type_0_mux1_FR1[ss_idx];
|
||||
M_scale = nr_ss_scale_M_mux1_FR1[ss_idx];
|
||||
pdcch_pdu->first_symbol = (ss_idx < 8)? ( (ssb_idx&1)? pdcch_pdu->n_symb : 0 ) : nr_ss_first_symb_idx_type_0_mux1_FR1[ss_idx - 8];
|
||||
}
|
||||
|
||||
else {
|
||||
AssertFatal(ss_idx<14 ,"Invalid search space index for multiplexing type 1 and FR2 %d\n", ss_idx);
|
||||
O = nr_ss_param_O_type_0_mux1_FR2[ss_idx];
|
||||
O_scale = nr_ss_scale_O_mux1_FR2[ss_idx];
|
||||
pdcch_pdu->nb_ss_sets_per_slot = nr_ss_sets_per_slot_type_0_FR2[ss_idx];
|
||||
M = nr_ss_param_M_type_0_mux1_FR2[ss_idx];
|
||||
M_scale = nr_ss_scale_M_mux1_FR2[ss_idx];
|
||||
pdcch_pdu->first_symbol = (ss_idx < 12)? ( (ss_idx&1)? 7 : 0 ) : 0;
|
||||
}
|
||||
pdcch_pdu->nb_slots = 2;
|
||||
pdcch_pdu->sfn_mod2 = (CEILIDIV( (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)), nb_slots_per_frame ) & 1)? 1 : 0;
|
||||
pdcch_pdu->first_slot = (((O<<mu)>>O_scale) + ((ssb_idx*M)>>M_scale)) % nb_slots_per_frame;
|
||||
|
||||
break;
|
||||
|
||||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE2:
|
||||
AssertFatal( ((scs_common==kHz120)&&(pdcch_scs==kHz60)) || ((scs_common==kHz240)&&(pdcch_scs==kHz120)),
|
||||
"Invalid scs_common/pdcch_scs combination %d/%d for Mux type 2\n", scs_common, pdcch_scs );
|
||||
AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);
|
||||
|
||||
pdcch_pdu->nb_slots = 1;
|
||||
|
||||
if ((scs_common==kHz120)&&(pdcch_scs==kHz60)) {
|
||||
pdcch_pdu->first_symbol = nr_ss_first_symb_idx_scs_120_60_mux2[ssb_idx&3];
|
||||
// Missing in pdcch_pdu sfn_C and n_C here and in else case
|
||||
}
|
||||
else {
|
||||
pdcch_pdu->first_symbol = ((ssb_idx&7)==4)?12 : ((ssb_idx&7)==4)?13 : nr_ss_first_symb_idx_scs_240_120_set1_mux2[ssb_idx&7]; //???
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NFAPI_NR_SSB_AND_CSET_MUX_PATTERN_TYPE3:
|
||||
AssertFatal( (scs_common==kHz120)&&(pdcch_scs==kHz120),
|
||||
"Invalid scs_common/pdcch_scs combination %d/%d for Mux type 3\n", scs_common, pdcch_scs );
|
||||
AssertFatal(ss_idx==0, "Search space index %d reserved for scs_common/pdcch_scs combination %d/%d", ss_idx, scs_common, pdcch_scs);
|
||||
|
||||
pdcch_pdu->first_symbol = nr_ss_first_symb_idx_scs_120_120_mux3[ssb_idx&3];
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid SSB and coreset multiplexing pattern %d\n", pdcch_pdu->mux_pattern);
|
||||
}
|
||||
pdcch_pdu->config_type = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
|
||||
pdcch_pdu->cr_mapping_type = NFAPI_NR_CCE_REG_MAPPING_INTERLEAVED;
|
||||
pdcch_pdu->precoder_granularity = NFAPI_NR_CSET_SAME_AS_REG_BUNDLE;
|
||||
pdcch_pdu->reg_bundle_size = 6;
|
||||
pdcch_pdu->interleaver_size = 2;
|
||||
// set initial banwidth part to full bandwidth
|
||||
pdcch_pdu->n_RB_BWP = N_RB;
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void config_uldci(const NR_SIB1_t *sib1,
|
||||
const NR_ServingCellConfigCommon_t *scc,
|
||||
const nfapi_nr_pusch_pdu_t *pusch_pdu,
|
||||
@@ -2445,17 +2227,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
UL_BWP->initial_BWPSize = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
UL_BWP->initial_BWPStart = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
// Set downlink MCS table
|
||||
if (DL_BWP->pdsch_Config &&
|
||||
DL_BWP->pdsch_Config->mcs_Table) {
|
||||
if (*DL_BWP->pdsch_Config->mcs_Table == 0)
|
||||
DL_BWP->mcsTableIdx = 1;
|
||||
else
|
||||
DL_BWP->mcsTableIdx = 2;
|
||||
} else
|
||||
DL_BWP->mcsTableIdx = 0;
|
||||
LOG_D(NR_MAC,"DL MCS Table Index: %d\n",DL_BWP->mcsTableIdx);
|
||||
|
||||
if (UL_BWP->pusch_Config == NULL || !UL_BWP->pusch_Config->transformPrecoder)
|
||||
UL_BWP->transform_precoding = !scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder;
|
||||
else
|
||||
@@ -2539,14 +2310,17 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
DL_BWP->dci_format = NR_DL_DCI_FORMAT_1_0;
|
||||
}
|
||||
|
||||
// Set uplink MCS table
|
||||
long *mcs_Table = NULL;
|
||||
if (UL_BWP->pusch_Config)
|
||||
mcs_Table = UL_BWP->transform_precoding ?
|
||||
UL_BWP->pusch_Config->mcs_Table :
|
||||
UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
|
||||
// Set MCS tables
|
||||
long *dl_mcs_Table = DL_BWP->pdsch_Config ? DL_BWP->pdsch_Config->mcs_Table : NULL;
|
||||
DL_BWP->mcsTableIdx = get_pdsch_mcs_table(dl_mcs_Table, DL_BWP->dci_format, NR_RNTI_C, target_ss);
|
||||
|
||||
UL_BWP->mcs_table = get_pusch_mcs_table(mcs_Table,
|
||||
long *ul_mcs_Table = NULL;
|
||||
if (UL_BWP->pusch_Config)
|
||||
ul_mcs_Table = UL_BWP->transform_precoding ?
|
||||
UL_BWP->pusch_Config->mcs_Table :
|
||||
UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
|
||||
|
||||
UL_BWP->mcs_table = get_pusch_mcs_table(ul_mcs_Table,
|
||||
UL_BWP->transform_precoding ? 0 : 1,
|
||||
UL_BWP->dci_format,
|
||||
NR_RNTI_C,
|
||||
|
||||
@@ -680,7 +680,8 @@ void evaluate_cqi_report(uint8_t *payload,
|
||||
int cumul_bits,
|
||||
uint8_t ri,
|
||||
NR_UE_info_t *UE,
|
||||
long *cqi_Table){
|
||||
uint8_t cqi_Table)
|
||||
{
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
|
||||
@@ -692,10 +693,7 @@ void evaluate_cqi_report(uint8_t *payload,
|
||||
// NR_CSI_ReportConfig__cqi_Table_table1 = 0
|
||||
// NR_CSI_ReportConfig__cqi_Table_table2 = 1
|
||||
// NR_CSI_ReportConfig__cqi_Table_table3 = 2
|
||||
if (cqi_Table)
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table = *cqi_Table;
|
||||
else
|
||||
AssertFatal(1==0,"CQI Table not present in RRC configuration\n");
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table = cqi_Table;
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb = temp_cqi;
|
||||
LOG_D(MAC,"Wide-band CQI for the first TB %d\n", temp_cqi);
|
||||
if (cqi_bitlen > 4) {
|
||||
@@ -707,8 +705,7 @@ void evaluate_cqi_report(uint8_t *payload,
|
||||
// TODO for wideband case and multiple TB
|
||||
const int cqi_idx = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb;
|
||||
const int mcs_table = UE->current_DL_BWP.mcsTableIdx;
|
||||
const int cqi_table = sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cqi_table;
|
||||
sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_table, cqi_idx);
|
||||
sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx);
|
||||
}
|
||||
|
||||
|
||||
@@ -785,6 +782,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type = NR_CSI_ReportConfig__reportQuantity_PR_NOTHING;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
|
||||
const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs];
|
||||
int cumul_bits = 0;
|
||||
int r_index = -1;
|
||||
@@ -796,6 +794,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
uint8_t li_bitlen = 0;
|
||||
uint8_t pmi_bitlen = 0;
|
||||
NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
|
||||
uint8_t cqi_table = (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_1 && csirep->cqi_Table) ? *csirep->cqi_Table : NR_CSI_ReportConfig__cqi_Table_table1;
|
||||
const NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
|
||||
if(pucchcsires->uplinkBandwidthPartId != ul_bwp->bwp_id)
|
||||
continue;
|
||||
@@ -823,7 +822,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
cumul_bits += ri_bitlen;
|
||||
if (r_index != -1)
|
||||
skip_zero_padding(&cumul_bits,csi_report,r_index,bitlen);
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,csirep->cqi_Table);
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI:
|
||||
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
|
||||
@@ -839,7 +838,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
pmi_bitlen = evaluate_pmi_report(payload,csi_report,cumul_bits,r_index,sched_ctrl);
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
|
||||
cumul_bits += pmi_bitlen;
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,csirep->cqi_Table);
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
|
||||
break;
|
||||
case NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_LI_PMI_CQI:
|
||||
cri_bitlen = csi_report->csi_meas_bitlen.cri_bitlen;
|
||||
@@ -857,7 +856,7 @@ void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
|
||||
pmi_bitlen = evaluate_pmi_report(payload,csi_report,cumul_bits,r_index,sched_ctrl);
|
||||
sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.csi_report_id = csi_report_id;
|
||||
cumul_bits += pmi_bitlen;
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,csirep->cqi_Table);
|
||||
evaluate_cqi_report(payload,csi_report,cumul_bits,r_index,UE,cqi_table);
|
||||
break;
|
||||
default:
|
||||
AssertFatal(1==0, "Invalid or not supported CSI measurement report\n");
|
||||
|
||||
@@ -1549,7 +1549,8 @@ void pf_ul(module_id_t module_id,
|
||||
NR_UE_info_t *UE_list[],
|
||||
int max_num_ue,
|
||||
int n_rb_sched,
|
||||
uint16_t *rballoc_mask) {
|
||||
uint16_t *rballoc_mask)
|
||||
{
|
||||
|
||||
const int CC_id = 0;
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[module_id];
|
||||
@@ -1887,12 +1888,16 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
|
||||
for (int i = 0; i < bwpSize; i++)
|
||||
rballoc_mask[i] = (i >= st && i <= e)*SL_to_bitmap(startSymbolIndex, nrOfSymbols);
|
||||
|
||||
int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
||||
int average_agg_level = 4; // TODO find a better estimation
|
||||
int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_ul(module_id,
|
||||
frame,
|
||||
slot,
|
||||
nr_mac->UE_info.list,
|
||||
2,
|
||||
max_sched_ues,
|
||||
len,
|
||||
rballoc_mask);
|
||||
return true;
|
||||
|
||||
@@ -221,25 +221,6 @@ int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config,
|
||||
nr_dci_format_t dci_format,
|
||||
uint8_t *pdsch_to_harq_feedback);
|
||||
|
||||
void nr_configure_css_dci_initial(nfapi_nr_dl_tti_pdcch_pdu_rel15_t* pdcch_pdu,
|
||||
nr_scs_e scs_common,
|
||||
nr_scs_e pdcch_scs,
|
||||
frequency_range_t freq_range,
|
||||
uint8_t rmsi_pdcch_config,
|
||||
uint8_t ssb_idx,
|
||||
uint8_t k_ssb,
|
||||
uint16_t sfn_ssb,
|
||||
uint8_t n_ssb,
|
||||
uint16_t nb_slots_per_frame,
|
||||
uint16_t N_RB);
|
||||
/*
|
||||
int nr_is_dci_opportunity(nfapi_nr_search_space_t search_space,
|
||||
nfapi_nr_coreset_t coreset,
|
||||
uint16_t frame,
|
||||
uint16_t slot,
|
||||
nfapi_nr_config_request_scf_t cfg);
|
||||
*/
|
||||
|
||||
int nr_get_pucch_resource(NR_ControlResourceSet_t *coreset,
|
||||
NR_PUCCH_Config_t *pucch_Config,
|
||||
int CCEIndex);
|
||||
|
||||
@@ -130,7 +130,6 @@ int dl_rrc_message_rrcSetup(module_id_t module_id, const f1ap_dl_rrc_message_t *
|
||||
ue_context_p->ue_context.SRB_configList,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
cellGroup->rlc_BearerToAddModList);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,948 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "assertions.h"
|
||||
#include "hashtable.h"
|
||||
#include "rlc_am.h"
|
||||
#include "rlc_am_segment.h"
|
||||
#include "rlc_am_timer_poll_retransmit.h"
|
||||
#include "mac_primitives.h"
|
||||
#include "rlc_primitives.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "LTE_UL-AM-RLC.h"
|
||||
#include "LTE_DL-AM-RLC.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t
|
||||
rlc_am_get_status_pdu_buffer_occupancy(
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
//Compute Max Status PDU size according to what has been received and not received in the window [vrR vrMS[
|
||||
// minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
|
||||
uint32_t nb_bits_to_transmit = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
|
||||
mem_block_t *cursor_p = rlc_pP->receiver_buffer.head;
|
||||
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
|
||||
int waited_so = 0;
|
||||
rlc_sn_t sn_cursor = rlc_pP->vr_r;
|
||||
rlc_sn_t sn_prev = rlc_pP->vr_r;
|
||||
rlc_sn_t sn_end = rlc_pP->vr_ms;
|
||||
bool segment_loop_end = false;
|
||||
|
||||
if (sn_prev != sn_end) {
|
||||
while ((RLC_AM_DIFF_SN(sn_prev,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)) && (cursor_p != NULL)) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
sn_cursor = pdu_info_cursor_p->sn;
|
||||
|
||||
// Add holes between sn_prev and sn_cursor
|
||||
while ((sn_prev != sn_cursor) && (sn_prev != sn_end)) {
|
||||
/* Add 1 NACK_SN + E1 + E2 */
|
||||
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
|
||||
sn_prev = RLC_AM_NEXT_SN(sn_prev);
|
||||
} //end while (sn_prev != sn_cursor)
|
||||
|
||||
/* Handle case sn_cursor is partially received */
|
||||
/* Each gap will add NACK_SN + E1 + E2 + SOStart + SOEnd */
|
||||
if ((((rlc_am_rx_pdu_management_t *)(cursor_p->data))->all_segments_received == 0) && (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r))) {
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
/* Fill for [0 SO[ if SO not null */
|
||||
if (pdu_info_cursor_p->so) {
|
||||
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
|
||||
} else {
|
||||
waited_so = pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
|
||||
/* Fill following gaps if any */
|
||||
while (!segment_loop_end) {
|
||||
if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) {
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
if (waited_so < pdu_info_cursor_p->so) {
|
||||
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
} else {
|
||||
/* contiguous segment: only update waited_so */
|
||||
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
|
||||
waited_so += pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next received PDU or PDU Segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
} else {
|
||||
/* Fill last gap assuming LSF is not received */
|
||||
nb_bits_to_transmit += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
segment_loop_end = true;
|
||||
}
|
||||
} // end while (!segment_loop_end)
|
||||
} // end if segments
|
||||
else {
|
||||
/* Go to next received PDU or PDU segment with different SN */
|
||||
do {
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info.sn == sn_cursor));
|
||||
}
|
||||
|
||||
sn_prev = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
} // end if (sn_prev != sn_end)
|
||||
|
||||
// round up to the greatest byte
|
||||
return ((nb_bits_to_transmit + 7) >> 3);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t
|
||||
rlc_am_get_buffer_occupancy_in_bytes (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
// priority of control trafic
|
||||
rlc_pP->status_buffer_occupancy = 0;
|
||||
|
||||
if ((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK)) {
|
||||
rlc_pP->status_buffer_occupancy = rlc_am_get_status_pdu_buffer_occupancy(rlc_pP);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : CONTROL PDU %d bytes \n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->status_buffer_occupancy);
|
||||
}
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
if ((rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy ) > 0) {
|
||||
LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : STATUS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->status_buffer_occupancy);
|
||||
LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : RETRANS BUFFER %d bytes \n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), rlc_pP->retrans_num_bytes_to_retransmit);
|
||||
LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" BO : SDU BUFFER %d bytes + li_overhead %d bytes header_overhead %d bytes (nb sdu not segmented %d)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->sdu_buffer_occupancy,
|
||||
0,
|
||||
0,
|
||||
rlc_pP->nb_sdu_no_segmented);
|
||||
}
|
||||
}
|
||||
|
||||
return rlc_pP->status_buffer_occupancy + rlc_pP->retrans_num_bytes_to_retransmit + rlc_pP->sdu_buffer_occupancy;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_release (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
) {
|
||||
// empty
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
config_req_rlc_am (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_am_info_t *config_am_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP
|
||||
) {
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
rlc_am_entity_t *l_rlc_p = NULL;
|
||||
hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
hashtable_rc_t h_rc;
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
l_rlc_p = &rlc_union_p->rlc.am;
|
||||
LOG_D(RLC,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
config_am_pP->max_retx_threshold,
|
||||
config_am_pP->poll_pdu,
|
||||
config_am_pP->poll_byte,
|
||||
config_am_pP->t_poll_retransmit,
|
||||
config_am_pP->t_reordering,
|
||||
config_am_pP->t_status_prohibit);
|
||||
rlc_am_init(ctxt_pP, l_rlc_p);
|
||||
rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
|
||||
rlc_am_configure(ctxt_pP, l_rlc_p,
|
||||
config_am_pP->max_retx_threshold,
|
||||
config_am_pP->poll_pdu,
|
||||
config_am_pP->poll_byte,
|
||||
config_am_pP->t_poll_retransmit,
|
||||
config_am_pP->t_reordering,
|
||||
config_am_pP->t_status_prohibit);
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ RLC NOT FOUND\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
|
||||
}
|
||||
}
|
||||
uint16_t pollPDU_tab[LTE_PollPDU_pInfinity+1]= {4,8,16,32,64,128,256,RLC_AM_POLL_PDU_INFINITE}; //PollPDU_pInfinity is chosen to 0xFFFF for now
|
||||
uint32_t maxRetxThreshold_tab[LTE_UL_AM_RLC__maxRetxThreshold_t32+1]= {1,2,3,4,6,8,16,32};
|
||||
uint32_t pollByte_tab[LTE_PollByte_spare1]= {25000,50000,75000,100000,125000,250000,375000,500000,750000,1000000,1250000,1500000,2000000,3000000,RLC_AM_POLL_BYTE_INFINITE}; // PollByte_kBinfinity is chosen to 0xFFFFFFFF for now
|
||||
uint32_t PollRetransmit_tab[LTE_T_PollRetransmit_spare5]= {5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500,800,1000,2000,4000};
|
||||
uint32_t am_t_Reordering_tab[32]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,1600};
|
||||
uint32_t t_StatusProhibit_tab[LTE_T_StatusProhibit_spare2]= {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,300,350,400,450,500,800,1000,1200,1600,2000,2400};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void config_req_rlc_am_asn1 (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const struct LTE_RLC_Config__am *const config_am_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP) {
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
rlc_am_entity_t *l_rlc_p = NULL;
|
||||
hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
hashtable_rc_t h_rc;
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
l_rlc_p = &rlc_union_p->rlc.am;
|
||||
|
||||
if ((config_am_pP->ul_AM_RLC.maxRetxThreshold <= LTE_UL_AM_RLC__maxRetxThreshold_t32) &&
|
||||
(config_am_pP->ul_AM_RLC.pollPDU<=LTE_PollPDU_pInfinity) &&
|
||||
(config_am_pP->ul_AM_RLC.pollByte<LTE_PollByte_spare1) &&
|
||||
(config_am_pP->ul_AM_RLC.t_PollRetransmit<LTE_T_PollRetransmit_spare5) &&
|
||||
(config_am_pP->dl_AM_RLC.t_Reordering<32) &&
|
||||
(config_am_pP->dl_AM_RLC.t_StatusProhibit<LTE_T_StatusProhibit_spare2) ) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d poll_pdu=%d poll_byte=%d t_poll_retransmit=%d t_reord=%d t_status_prohibit=%d)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
|
||||
pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
|
||||
pollByte_tab[config_am_pP->ul_AM_RLC.pollByte],
|
||||
PollRetransmit_tab[config_am_pP->ul_AM_RLC.t_PollRetransmit],
|
||||
am_t_Reordering_tab[config_am_pP->dl_AM_RLC.t_Reordering],
|
||||
t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
|
||||
rlc_am_init(ctxt_pP, l_rlc_p);
|
||||
rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
|
||||
rlc_am_configure(ctxt_pP, l_rlc_p,
|
||||
maxRetxThreshold_tab[config_am_pP->ul_AM_RLC.maxRetxThreshold],
|
||||
pollPDU_tab[config_am_pP->ul_AM_RLC.pollPDU],
|
||||
pollByte_tab[config_am_pP->ul_AM_RLC.pollByte],
|
||||
PollRetransmit_tab[config_am_pP->ul_AM_RLC.t_PollRetransmit],
|
||||
am_t_Reordering_tab[config_am_pP->dl_AM_RLC.t_Reordering],
|
||||
t_StatusProhibit_tab[config_am_pP->dl_AM_RLC.t_StatusProhibit]);
|
||||
} else {
|
||||
LOG_D(RLC,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT"ILLEGAL CONFIG_REQ (max_retx_threshold=%ld poll_pdu=%ld poll_byte=%ld t_poll_retransmit=%ld t_reord=%ld t_status_prohibit=%ld), RLC-AM NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
config_am_pP->ul_AM_RLC.maxRetxThreshold,
|
||||
config_am_pP->ul_AM_RLC.pollPDU,
|
||||
config_am_pP->ul_AM_RLC.pollByte,
|
||||
config_am_pP->ul_AM_RLC.t_PollRetransmit,
|
||||
config_am_pP->dl_AM_RLC.t_Reordering,
|
||||
config_am_pP->dl_AM_RLC.t_StatusProhibit);
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"CONFIG_REQ RLC NOT FOUND\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_stat_req (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
unsigned int *stat_tx_pdcp_sdu,
|
||||
unsigned int *stat_tx_pdcp_bytes,
|
||||
unsigned int *stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int *stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int *stat_tx_data_pdu,
|
||||
unsigned int *stat_tx_data_bytes,
|
||||
unsigned int *stat_tx_retransmit_pdu_by_status,
|
||||
unsigned int *stat_tx_retransmit_bytes_by_status,
|
||||
unsigned int *stat_tx_retransmit_pdu,
|
||||
unsigned int *stat_tx_retransmit_bytes,
|
||||
unsigned int *stat_tx_control_pdu,
|
||||
unsigned int *stat_tx_control_bytes,
|
||||
unsigned int *stat_rx_pdcp_sdu,
|
||||
unsigned int *stat_rx_pdcp_bytes,
|
||||
unsigned int *stat_rx_data_pdus_duplicate,
|
||||
unsigned int *stat_rx_data_bytes_duplicate,
|
||||
unsigned int *stat_rx_data_pdu,
|
||||
unsigned int *stat_rx_data_bytes,
|
||||
unsigned int *stat_rx_data_pdu_dropped,
|
||||
unsigned int *stat_rx_data_bytes_dropped,
|
||||
unsigned int *stat_rx_data_pdu_out_of_window,
|
||||
unsigned int *stat_rx_data_bytes_out_of_window,
|
||||
unsigned int *stat_rx_control_pdu,
|
||||
unsigned int *stat_rx_control_bytes,
|
||||
unsigned int *stat_timer_reordering_timed_out,
|
||||
unsigned int *stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int *stat_timer_status_prohibit_timed_out) {
|
||||
*stat_tx_pdcp_sdu = rlc_pP->stat_tx_pdcp_sdu;
|
||||
*stat_tx_pdcp_bytes = rlc_pP->stat_tx_pdcp_bytes;
|
||||
*stat_tx_pdcp_sdu_discarded = rlc_pP->stat_tx_pdcp_sdu_discarded;
|
||||
*stat_tx_pdcp_bytes_discarded = rlc_pP->stat_tx_pdcp_bytes_discarded;
|
||||
*stat_tx_data_pdu = rlc_pP->stat_tx_data_pdu;
|
||||
*stat_tx_data_bytes = rlc_pP->stat_tx_data_bytes;
|
||||
*stat_tx_retransmit_pdu_by_status = rlc_pP->stat_tx_retransmit_pdu_by_status;
|
||||
*stat_tx_retransmit_bytes_by_status = rlc_pP->stat_tx_retransmit_bytes_by_status;
|
||||
*stat_tx_retransmit_pdu = rlc_pP->stat_tx_retransmit_pdu;
|
||||
*stat_tx_retransmit_bytes = rlc_pP->stat_tx_retransmit_bytes;
|
||||
*stat_tx_control_pdu = rlc_pP->stat_tx_control_pdu;
|
||||
*stat_tx_control_bytes = rlc_pP->stat_tx_control_bytes;
|
||||
*stat_rx_pdcp_sdu = rlc_pP->stat_rx_pdcp_sdu;
|
||||
*stat_rx_pdcp_bytes = rlc_pP->stat_rx_pdcp_bytes;
|
||||
*stat_rx_data_pdus_duplicate = rlc_pP->stat_rx_data_pdus_duplicate;
|
||||
*stat_rx_data_bytes_duplicate = rlc_pP->stat_rx_data_bytes_duplicate;
|
||||
*stat_rx_data_pdu = rlc_pP->stat_rx_data_pdu;
|
||||
*stat_rx_data_bytes = rlc_pP->stat_rx_data_bytes;
|
||||
*stat_rx_data_pdu_dropped = rlc_pP->stat_rx_data_pdu_dropped;
|
||||
*stat_rx_data_bytes_dropped = rlc_pP->stat_rx_data_bytes_dropped;
|
||||
*stat_rx_data_pdu_out_of_window = rlc_pP->stat_rx_data_pdu_out_of_window;
|
||||
*stat_rx_data_bytes_out_of_window = rlc_pP->stat_rx_data_bytes_out_of_window;
|
||||
*stat_rx_control_pdu = rlc_pP->stat_rx_control_pdu;
|
||||
*stat_rx_control_bytes = rlc_pP->stat_rx_control_bytes;
|
||||
*stat_timer_reordering_timed_out = rlc_pP->stat_timer_reordering_timed_out;
|
||||
*stat_timer_poll_retransmit_timed_out = rlc_pP->stat_timer_poll_retransmit_timed_out;
|
||||
*stat_timer_status_prohibit_timed_out = rlc_pP->stat_timer_status_prohibit_timed_out;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_get_pdus (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
) {
|
||||
//int display_flag = 0;
|
||||
// 5.1.3.1 Transmit operations
|
||||
// 5.1.3.1.1
|
||||
// General
|
||||
// The transmitting side of an AM RLC entity shall prioritize transmission of RLC control PDUs over RLC data PDUs.
|
||||
// The transmitting side of an AM RLC entity shall prioritize retransmission of RLC data PDUs over transmission of new
|
||||
// AMD PDUs.
|
||||
switch (rlc_pP->protocol_state) {
|
||||
case RLC_NULL_STATE:
|
||||
break;
|
||||
|
||||
case RLC_DATA_TRANSFER_READY_STATE:
|
||||
|
||||
// TRY TO SEND CONTROL PDU FIRST
|
||||
if ((rlc_pP->nb_bytes_requested_by_mac >= 2) &&
|
||||
((rlc_pP->status_requested) && !(rlc_pP->status_requested & RLC_AM_STATUS_NO_TX_MASK))) {
|
||||
// When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
|
||||
// - if t-StatusProhibit is not running:
|
||||
// - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
|
||||
// - else:
|
||||
// - at the first transmission opportunity indicated by lower layer after t-StatusProhibit expires, construct a single
|
||||
// STATUS PDU even if status reporting was triggered several times while t-StatusProhibit was running and
|
||||
// deliver it to lower layer;
|
||||
//
|
||||
// When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall:
|
||||
// - start t-StatusProhibit.
|
||||
rlc_am_send_status_pdu(ctxt_pP, rlc_pP);
|
||||
mem_block_t *pdu = list_remove_head(&rlc_pP->control_pdu_list);
|
||||
|
||||
if (pdu) {
|
||||
list_add_tail_eurecom (pdu, &rlc_pP->pdus_to_mac_layer);
|
||||
RLC_AM_CLEAR_ALL_STATUS(rlc_pP->status_requested);
|
||||
rlc_pP->status_buffer_occupancy = 0;
|
||||
rlc_am_start_timer_status_prohibit(ctxt_pP, rlc_pP);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" DELAYED SENT STATUS PDU (Available MAC Data %u)(T-PROHIBIT %u) (DELAY FLAG %u)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->nb_bytes_requested_by_mac,rlc_pP->t_status_prohibit.ms_time_out,(rlc_pP->status_requested & RLC_AM_STATUS_TRIGGERED_DELAYED));
|
||||
}
|
||||
|
||||
// THEN TRY TO SEND RETRANS PDU
|
||||
if ((rlc_pP->retrans_num_bytes_to_retransmit) && (rlc_pP->nb_bytes_requested_by_mac > 2)) {
|
||||
/* Get 1 AM data PDU or PDU segment to retransmit */
|
||||
mem_block_t *pdu_retx = rlc_am_get_pdu_to_retransmit(ctxt_pP, rlc_pP);
|
||||
|
||||
if (pdu_retx != NULL) {
|
||||
list_add_tail_eurecom (pdu_retx, &rlc_pP->pdus_to_mac_layer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// THEN TRY TO SEND NEW DATA PDU
|
||||
if ((rlc_pP->nb_bytes_requested_by_mac > 2) && (rlc_pP->sdu_buffer_occupancy) && (rlc_pP->vt_s != rlc_pP->vt_ms)) {
|
||||
rlc_am_segment_10(ctxt_pP, rlc_pP);
|
||||
list_add_list (&rlc_pP->segmentation_pdu_list, &rlc_pP->pdus_to_mac_layer);
|
||||
|
||||
if (rlc_pP->pdus_to_mac_layer.head != NULL) {
|
||||
rlc_pP->stat_tx_data_pdu += 1;
|
||||
rlc_pP->stat_tx_data_bytes += (((struct mac_tb_req *)(rlc_pP->pdus_to_mac_layer.head->data))->tb_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQ UNKNOWN PROTOCOL STATE 0x%02X\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->protocol_state);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_rx (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
void *const arg_pP,
|
||||
struct mac_data_ind data_indP
|
||||
) {
|
||||
rlc_am_entity_t *rlc = (rlc_am_entity_t *) arg_pP;
|
||||
|
||||
switch (rlc->protocol_state) {
|
||||
case RLC_NULL_STATE:
|
||||
LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR MAC_DATA_IND IN RLC_NULL_STATE\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP, rlc));
|
||||
list_free (&data_indP.data);
|
||||
break;
|
||||
|
||||
case RLC_DATA_TRANSFER_READY_STATE:
|
||||
rlc_am_receive_routing (ctxt_pP, rlc, data_indP);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" TX UNKNOWN PROTOCOL STATE 0x%02X\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP, rlc), rlc->protocol_state);
|
||||
list_free (&data_indP.data);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_status_resp
|
||||
rlc_am_mac_status_indication (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
void *const rlc_pP,
|
||||
struct mac_status_ind tx_statusP,
|
||||
const eNB_flag_t enb_flagP) {
|
||||
struct mac_status_resp status_resp;
|
||||
uint16_t sdu_size = 0;
|
||||
uint16_t sdu_remaining_size = 0;
|
||||
int32_t diff_time=0;
|
||||
rlc_am_entity_t *rlc = (rlc_am_entity_t *) rlc_pP;
|
||||
status_resp.buffer_occupancy_in_bytes = 0;
|
||||
status_resp.buffer_occupancy_in_pdus = 0;
|
||||
status_resp.head_sdu_remaining_size_to_send = 0;
|
||||
status_resp.head_sdu_creation_time = 0;
|
||||
status_resp.head_sdu_is_segmented = 0;
|
||||
status_resp.rlc_info.rlc_protocol_state = rlc->protocol_state;
|
||||
|
||||
/* TODO: remove this hack. Problem is: there is a race.
|
||||
* UE comes. SRB2 is configured via message to RRC.
|
||||
* At some point the RLC AM is created but not configured yet.
|
||||
* At this moment (I think) MAC calls mac_rlc_status_ind
|
||||
* which calls this function. But the init was not finished yet
|
||||
* and we have a crash below when testing mem_block != NULL.
|
||||
*/
|
||||
if (rlc->input_sdus == NULL) return status_resp;
|
||||
|
||||
if (rlc->last_absolute_subframe_status_indication != (PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP))) {
|
||||
rlc_am_check_timer_poll_retransmit(ctxt_pP, rlc);
|
||||
rlc_am_check_timer_reordering(ctxt_pP, rlc);
|
||||
rlc_am_check_timer_status_prohibit(ctxt_pP, rlc);
|
||||
}
|
||||
|
||||
rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
|
||||
|
||||
status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc);
|
||||
|
||||
// For eNB scheduler : Add Max RLC header size for new PDU
|
||||
// For UE : do not add RLC header part to be compliant with BSR definition in 36.321
|
||||
if (enb_flagP == ENB_FLAG_YES) {
|
||||
uint32_t max_li_overhead = 0;
|
||||
uint32_t header_overhead = 0;
|
||||
|
||||
if (rlc->nb_sdu_no_segmented > 1) {
|
||||
/* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/
|
||||
uint32_t num_li = rlc->nb_sdu_no_segmented - 1;
|
||||
max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
|
||||
}
|
||||
|
||||
if (rlc->sdu_buffer_occupancy > 0) {
|
||||
header_overhead = 2;
|
||||
}
|
||||
|
||||
status_resp.buffer_occupancy_in_bytes += (header_overhead + max_li_overhead);
|
||||
}
|
||||
|
||||
if ((rlc->input_sdus[rlc->current_sdu_index].mem_block != NULL) && (status_resp.buffer_occupancy_in_bytes)) {
|
||||
//status_resp.buffer_occupancy_in_bytes += ((rlc_am_entity_t *) rlc)->tx_header_min_length_in_bytes;
|
||||
status_resp.buffer_occupancy_in_pdus = rlc->nb_sdu;
|
||||
diff_time = ctxt_pP->frame - ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_creation_time;
|
||||
status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time : (uint32_t)(0xffffffff - diff_time + ctxt_pP->frame) ;
|
||||
sdu_size = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_size;
|
||||
sdu_remaining_size = ((rlc_am_tx_sdu_management_t *) (rlc->input_sdus[rlc->current_sdu_index].mem_block->data))->sdu_remaining_size;
|
||||
status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
|
||||
|
||||
if (sdu_size == sdu_remaining_size) {
|
||||
status_resp.head_sdu_is_segmented = 0;
|
||||
} else {
|
||||
status_resp.head_sdu_is_segmented = 1;
|
||||
}
|
||||
} else {
|
||||
/* Not so many possibilities ... */
|
||||
/* either buffer_occupancy_in_bytes = 0 and that's it */
|
||||
/* or we have segmented all received SDUs and buffer occupancy is then made of retransmissions and/or status pdu pending */
|
||||
/* then consider only retransmission buffer for the specific BO values used by eNB scheduler (not used up to now...) */
|
||||
if (rlc->retrans_num_bytes_to_retransmit) {
|
||||
status_resp.buffer_occupancy_in_pdus = rlc->retrans_num_pdus;
|
||||
status_resp.head_sdu_remaining_size_to_send = rlc->retrans_num_bytes_to_retransmit;
|
||||
status_resp.head_sdu_is_segmented = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) -> %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc),
|
||||
status_resp.buffer_occupancy_in_bytes);
|
||||
}
|
||||
|
||||
return status_resp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_data_req
|
||||
rlc_am_mac_data_request (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
void *const rlc_pP,
|
||||
const eNB_flag_t enb_flagP
|
||||
) {
|
||||
struct mac_data_req data_req;
|
||||
rlc_am_entity_t *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
|
||||
unsigned int nb_bytes_requested_by_mac = ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac;
|
||||
rlc_am_pdu_info_t pdu_info;
|
||||
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
|
||||
mem_block_t *tb_p;
|
||||
tb_size_t tb_size_in_bytes;
|
||||
int num_nack;
|
||||
char message_string[9000];
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
/* for no gcc warnings */
|
||||
(void)num_nack;
|
||||
(void)message_string;
|
||||
(void)message_string_size;
|
||||
(void)octet_index;
|
||||
(void)index;
|
||||
list_init (&data_req.data, NULL);
|
||||
rlc_am_get_pdus (ctxt_pP, l_rlc_p);
|
||||
list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
|
||||
|
||||
//((rlc_am_entity_t *) rlc_pP)->tx_pdus += data_req.data.nb_elements;
|
||||
if ((nb_bytes_requested_by_mac + data_req.data.nb_elements) > 0) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_DATA_REQUEST %05d BYTES REQUESTED -> %d TBs\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
nb_bytes_requested_by_mac,
|
||||
data_req.data.nb_elements);
|
||||
}
|
||||
|
||||
if (enb_flagP) {
|
||||
// redundant in UE MAC Tx processing and not used in eNB ...
|
||||
data_req.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, l_rlc_p);
|
||||
}
|
||||
|
||||
data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
|
||||
|
||||
if ( (LOG_DEBUGFLAG(DEBUG_RLC))&& data_req.data.nb_elements > 0) {
|
||||
tb_p = data_req.data.head;
|
||||
|
||||
while (tb_p != NULL) {
|
||||
rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t *)((struct mac_tb_req *) (tb_p->data))->data_ptr;
|
||||
tb_size_in_bytes = ((struct mac_tb_req *) (tb_p->data))->tb_size;
|
||||
|
||||
if ((((struct mac_tb_req *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
|
||||
if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size = 0;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", tb_size_in_bytes);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
|
||||
|
||||
if (pdu_info.rf) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA REQ: AMD PDU segment\n\n");
|
||||
} else {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA REQ: AMD PDU\n\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " D/C : %u\n", pdu_info.d_c);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " RF : %u\n", pdu_info.rf);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " P : %u\n", pdu_info.p);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " FI : %u\n", pdu_info.fi);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E : %u\n", pdu_info.e);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SN : %u\n", pdu_info.sn);
|
||||
|
||||
if (pdu_info.rf) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LSF : %u\n", pdu_info.lsf);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SO : %u\n", pdu_info.so);
|
||||
}
|
||||
|
||||
if (pdu_info.e) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension : \n");
|
||||
|
||||
for (index=0; index < pdu_info.num_li; index++) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LI : %u\n", pdu_info.li_list[index]);
|
||||
}
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
LOG_UI(RLC,"%s\n",message_string);
|
||||
} /* LOG_DEBUGFLAG(DEBUG_RLC) */
|
||||
}
|
||||
} else {
|
||||
if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &l_rlc_p->control_pdu_info) >= 0) {
|
||||
tb_size_in_bytes = ((struct mac_tb_req *) (tb_p->data))->tb_size; //tb_size_in_bytes modified by rlc_am_get_control_pdu_infos!
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size = 0;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", tb_size_in_bytes);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA REQ: STATUS PDU\n\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " D/C : %u\n", l_rlc_p->control_pdu_info.d_c);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " CPT : %u\n", l_rlc_p->control_pdu_info.cpt);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ACK_SN : %u\n", l_rlc_p->control_pdu_info.ack_sn);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E1 : %u\n", l_rlc_p->control_pdu_info.e1);
|
||||
|
||||
for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
|
||||
if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " NACK SN %04d SO START %05d SO END %05d",
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
|
||||
} else {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " NACK SN %04d", l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_UI(RLC,"%s\n",message_string);
|
||||
} /* LOG_DEBUGFLAG(DEBUG_RLC) */
|
||||
}
|
||||
}
|
||||
|
||||
tb_p = tb_p->next;
|
||||
} /* while */
|
||||
} /* data_req.data.nb_elements > 0 */
|
||||
|
||||
data_req.buffer_occupancy_in_pdus = 0;
|
||||
return data_req;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_mac_data_indication (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
void *const rlc_pP,
|
||||
struct mac_data_ind data_indP
|
||||
) {
|
||||
rlc_am_entity_t *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
|
||||
/*rlc_am_control_pdu_info_t control_pdu_info;
|
||||
int num_li;
|
||||
int16_t tb_size;*/
|
||||
rlc_am_pdu_info_t pdu_info;
|
||||
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p;
|
||||
mem_block_t *tb_p;
|
||||
sdu_size_t tb_size_in_bytes;
|
||||
int num_nack;
|
||||
char message_string[7000];
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
/* for no gcc warnings */
|
||||
(void)num_nack;
|
||||
(void)message_string;
|
||||
(void)message_string_size;
|
||||
(void)octet_index;
|
||||
(void)index;
|
||||
(void)l_rlc_p; /* avoid gcc warning "unused variable" */
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
if (data_indP.data.nb_elements > 0) {
|
||||
tb_p = data_indP.data.head;
|
||||
|
||||
while (tb_p != NULL) {
|
||||
rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t *)((struct mac_tb_ind *) (tb_p->data))->data_ptr;
|
||||
tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
|
||||
|
||||
if ((((struct mac_tb_ind *) (tb_p->data))->data_ptr[0] & RLC_DC_MASK) == RLC_DC_DATA_PDU ) {
|
||||
if (rlc_am_get_data_pdu_infos(ctxt_pP,l_rlc_p,rlc_am_pdu_sn_10_p, tb_size_in_bytes, &pdu_info) >= 0) {
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", tb_size_in_bytes);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
|
||||
|
||||
if (pdu_info.rf) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA IND: AMD PDU segment\n\n");
|
||||
} else {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA IND: AMD PDU\n\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " D/C : %u\n", pdu_info.d_c);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " RF : %u\n", pdu_info.rf);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " P : %u\n", pdu_info.p);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " FI : %u\n", pdu_info.fi);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E : %u\n", pdu_info.e);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SN : %u\n", pdu_info.sn);
|
||||
|
||||
if (pdu_info.rf) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LSF : %u\n", pdu_info.lsf);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SO : %u\n", pdu_info.so);
|
||||
}
|
||||
|
||||
if (pdu_info.e) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension : \n");
|
||||
|
||||
for (index=0; index < pdu_info.num_li; index++) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LI : %u\n", pdu_info.li_list[index]);
|
||||
}
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
LOG_UI(RLC,"%s\n",message_string);
|
||||
} /* LOG_DEBUGFLAG */
|
||||
}
|
||||
} else {
|
||||
if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, &tb_size_in_bytes, &l_rlc_p->control_pdu_info) >= 0) {
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size = 0;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", ((struct mac_tb_ind *) (tb_p->data))->size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC AM DATA IND: STATUS PDU\n\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " D/C : %u\n", l_rlc_p->control_pdu_info.d_c);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " CPT : %u\n", l_rlc_p->control_pdu_info.cpt);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ACK_SN : %u\n", l_rlc_p->control_pdu_info.ack_sn);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E1 : %u\n", l_rlc_p->control_pdu_info.e1);
|
||||
|
||||
for (num_nack = 0; num_nack < l_rlc_p->control_pdu_info.num_nack; num_nack++) {
|
||||
if (l_rlc_p->control_pdu_info.nack_list[num_nack].e2) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " NACK SN %04d SO START %05d SO END %05d",
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn,
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].so_start,
|
||||
l_rlc_p->control_pdu_info.nack_list[num_nack].so_end);
|
||||
} else {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " NACK SN %04d", l_rlc_p->control_pdu_info.nack_list[num_nack].nack_sn);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_UI(RLC, "%s\n",message_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tb_p = tb_p->next;
|
||||
}
|
||||
}
|
||||
} /* LOG_DEBUGFLAG(RLC) || MESSAGE_TRACE_GENERATOR) */
|
||||
|
||||
rlc_am_rx (ctxt_pP, rlc_pP, data_indP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_data_req (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
void *const rlc_pP,
|
||||
mem_block_t *const sdu_pP) {
|
||||
rlc_am_entity_t *l_rlc_p = (rlc_am_entity_t *) rlc_pP;
|
||||
uint32_t mui;
|
||||
uint16_t data_offset;
|
||||
uint16_t data_size;
|
||||
char message_string[7000];
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
RLC_AM_MUTEX_LOCK(&l_rlc_p->lock_input_sdus, ctxt_pP, l_rlc_p);
|
||||
|
||||
if ((l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block == NULL) &&
|
||||
(l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmented == 0) &&
|
||||
(((l_rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE) != l_rlc_p->current_sdu_index)) {
|
||||
memset(&l_rlc_p->input_sdus[l_rlc_p->next_sdu_index], 0, sizeof(rlc_am_tx_sdu_management_t));
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block = sdu_pP;
|
||||
mui = ((struct rlc_am_data_req *) (sdu_pP->data))->mui;
|
||||
data_offset = ((struct rlc_am_data_req *) (sdu_pP->data))->data_offset;
|
||||
data_size = ((struct rlc_am_data_req *) (sdu_pP->data))->data_size;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "SDU size : %u\n", data_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "MUI : %u\n", mui);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "CONF : %u\n", ((struct rlc_am_data_req *) (sdu_pP->data))->conf);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < data_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", ((uint8_t *)(&sdu_pP->data[data_offset]))[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
LOG_UI(RLC, "%s\n", message_string);
|
||||
} /* LOG_DEBUGFLAG(RLC) */
|
||||
|
||||
l_rlc_p->stat_tx_pdcp_sdu += 1;
|
||||
l_rlc_p->stat_tx_pdcp_bytes += data_size;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mui = mui;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_size = data_size;
|
||||
l_rlc_p->sdu_buffer_occupancy += data_size;
|
||||
l_rlc_p->nb_sdu += 1;
|
||||
l_rlc_p->nb_sdu_no_segmented += 1;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].first_byte = (uint8_t *)(&sdu_pP->data[data_offset]);
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_remaining_size = l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_size;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_segmented_size = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].sdu_creation_time = ctxt_pP->frame;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].nb_pdus = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].nb_pdus_ack = 0;
|
||||
//l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].nb_pdus_time = 0;
|
||||
//l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].nb_pdus_internal_use = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.discarded = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmented = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmentation_in_progress = 0;
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.no_new_sdu_segmented_in_last_pdu = 0;
|
||||
//l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].li_index_for_discard = -1;
|
||||
l_rlc_p->next_sdu_index = (l_rlc_p->next_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
|
||||
if (l_rlc_p->channel_id <3) {
|
||||
LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ size %d Bytes, NB SDU %d current_sdu_index=%d next_sdu_index=%d conf %d mui %d vtA %d vtS %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
data_size,
|
||||
l_rlc_p->nb_sdu,
|
||||
l_rlc_p->current_sdu_index,
|
||||
l_rlc_p->next_sdu_index,
|
||||
((struct rlc_am_data_req *) (sdu_pP->data))->conf,
|
||||
mui,
|
||||
l_rlc_p->vt_a,
|
||||
l_rlc_p->vt_s);
|
||||
}
|
||||
} else {
|
||||
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ BUFFER FULL, NB SDU %d current_sdu_index=%d next_sdu_index=%d size_input_sdus_buffer=%d vtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
l_rlc_p->nb_sdu,
|
||||
l_rlc_p->current_sdu_index,
|
||||
l_rlc_p->next_sdu_index,
|
||||
RLC_AM_SDU_CONTROL_BUFFER_SIZE,
|
||||
l_rlc_p->vt_a,
|
||||
l_rlc_p->vt_s);
|
||||
LOG_W(RLC, " input_sdus[].mem_block=%p next input_sdus[].flags.segmented=%d\n",
|
||||
l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].mem_block, l_rlc_p->input_sdus[l_rlc_p->next_sdu_index].flags.segmented);
|
||||
l_rlc_p->stat_tx_pdcp_sdu_discarded += 1;
|
||||
l_rlc_p->stat_tx_pdcp_bytes_discarded += ((struct rlc_am_data_req *) (sdu_pP->data))->data_size;
|
||||
free_mem_block (sdu_pP, __func__);
|
||||
#if STOP_ON_IP_TRAFFIC_OVERLOAD
|
||||
AssertFatal(0, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_REQ size %d Bytes, SDU DROPPED, INPUT BUFFER OVERFLOW NB SDU %d current_sdu_index=%d next_sdu_index=%d \n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
data_size,
|
||||
l_rlc_p->nb_sdu,
|
||||
l_rlc_p->current_sdu_index,
|
||||
l_rlc_p->next_sdu_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
RLC_AM_MUTEX_UNLOCK(&l_rlc_p->lock_input_sdus);
|
||||
}
|
||||
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am.h
|
||||
* \brief This file, and only this file must be included by code that interact with RLC AM layer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_impl_ RLC AM Layer Reference Implementation
|
||||
* @ingroup _rlc_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
# ifndef __RLC_AM_H__
|
||||
# define __RLC_AM_H__
|
||||
# include "platform_types.h"
|
||||
# include "rlc_def.h"
|
||||
# include "rlc_def_lte.h"
|
||||
# include "rlc_am_constants.h"
|
||||
# include "rlc_am_structs.h"
|
||||
# include "rlc_am_entity.h"
|
||||
# include "rlc_am_windows.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_am_in_sdu.h"
|
||||
# include "rlc_am_segment.h"
|
||||
# include "rlc_am_segments_holes.h"
|
||||
# include "rlc_am_timer_poll_retransmit.h"
|
||||
# include "rlc_am_timer_reordering.h"
|
||||
# include "rlc_am_timer_status_prohibit.h"
|
||||
# include "rlc_am_retransmit.h"
|
||||
# include "rlc_am_receiver.h"
|
||||
# include "rlc_am_status_report.h"
|
||||
# include "rlc_am_rx_list.h"
|
||||
# include "rlc_am_reassembly.h"
|
||||
# include "rlc_am_init.h"
|
||||
# include "LTE_RLC-Config.h"
|
||||
# include "assertions.h"
|
||||
//# include "rlc_am_test.h"
|
||||
|
||||
|
||||
#define PROTOCOL_RLC_AM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld]"
|
||||
#define PROTOCOL_RLC_AM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
|
||||
(rLC_Pp->is_data_plane) ? "DRB AM" : "SRB AM",\
|
||||
rLC_Pp->rb_id
|
||||
|
||||
#define PROTOCOL_RLC_AM_MSC_FMT "[RNTI %" PRIx16 " %s %02ld]"
|
||||
#define PROTOCOL_RLC_AM_MSC_ARGS(CTXT_Pp, rLC_Pp) \
|
||||
CTXT_Pp->rnti,\
|
||||
(rLC_Pp->is_data_plane) ? "DRB AM" : "SRB AM",\
|
||||
rLC_Pp->rb_id
|
||||
|
||||
|
||||
#if defined(TRACE_RLC_MUTEX)
|
||||
#define RLC_AM_MUTEX_LOCK(mUTEX, cTXT, rLC) \
|
||||
do {\
|
||||
int pmtl_rc = pthread_mutex_trylock(mUTEX);\
|
||||
if (pmtl_rc != 0){\
|
||||
if (pmtl_rc == EBUSY) {\
|
||||
pthread_mutex_lock(mUTEX);\
|
||||
}\
|
||||
}\
|
||||
} while (0);
|
||||
#else
|
||||
#define RLC_AM_MUTEX_LOCK(mUTEX, cTXT, rLC) pthread_mutex_lock(mUTEX)
|
||||
#endif
|
||||
|
||||
#define RLC_AM_MUTEX_UNLOCK(mUTEX) pthread_mutex_unlock(mUTEX)
|
||||
|
||||
/*! \fn void rlc_am_release (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP)
|
||||
* \brief Empty function, TO DO.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_release (
|
||||
const protocol_ctxt_t* const ctxtP,
|
||||
rlc_am_entity_t * const rlc_pP);
|
||||
|
||||
/** @addtogroup _rlc_am_init_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! \fn void config_req_rlc_am (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, rlc_am_info_t * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
|
||||
* \brief Configure the UL and DL parameters of the RLC AM
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] config_amP Configuration parameters for RLC AM instance.
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void
|
||||
config_req_rlc_am (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_am_info_t * config_am_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP
|
||||
);
|
||||
|
||||
/*! \fn void config_req_rlc_am_asn1 (const protocol_ctxt_t* const ctxtP, const srb_flag_t srb_flagP, struct RLC_Config__am * config_amP, rb_id_t rb_idP, logical_chan_id_t chan_idP)
|
||||
* \brief Configure the UL and DL parameters of the RLC AM with the asn1c autogenerated pameters structs
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] config_amP Configuration parameters for RLC AM instance.
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void config_req_rlc_am_asn1 (
|
||||
const protocol_ctxt_t* const ctxtP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const struct LTE_RLC_Config__am * const config_amP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP);
|
||||
|
||||
/** @} */
|
||||
|
||||
/*! \fn void rlc_am_stat_req (
|
||||
const protocol_ctxt_t* const ctxtP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
unsigned int* stat_tx_pdcp_sdu,
|
||||
unsigned int* stat_tx_pdcp_bytes,
|
||||
unsigned int* stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int* stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int* stat_tx_data_pdu,
|
||||
unsigned int* stat_tx_data_bytes,
|
||||
unsigned int* stat_tx_retransmit_pdu_by_status,
|
||||
unsigned int* stat_tx_retransmit_bytes_by_status,
|
||||
unsigned int* stat_tx_retransmit_pdu,
|
||||
unsigned int* stat_tx_retransmit_bytes,
|
||||
unsigned int* stat_tx_control_pdu,
|
||||
unsigned int* stat_tx_control_bytes,
|
||||
unsigned int* stat_rx_pdcp_sdu,
|
||||
unsigned int* stat_rx_pdcp_bytes,
|
||||
unsigned int* stat_rx_data_pdus_duplicate,
|
||||
unsigned int* stat_rx_data_bytes_duplicate,
|
||||
unsigned int* stat_rx_data_pdu,
|
||||
unsigned int* stat_rx_data_bytes,
|
||||
unsigned int* stat_rx_data_pdu_dropped,
|
||||
unsigned int* stat_rx_data_bytes_dropped,
|
||||
unsigned int* stat_rx_data_pdu_out_of_window,
|
||||
unsigned int* stat_rx_data_bytes_out_of_window,
|
||||
unsigned int* stat_rx_control_pdu,
|
||||
unsigned int* stat_rx_control_bytes,
|
||||
unsigned int* stat_timer_reordering_timed_out,
|
||||
unsigned int* stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int* stat_timer_status_prohibit_timed_out)
|
||||
* \brief Request TX and RX statistics of a RLC AM protocol instance.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[out] stat_tx_pdcp_sdu Number of SDUs coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_bytes Number of bytes coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_sdu_discarded Number of discarded SDUs coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_bytes_discarded Number of discarded bytes coming from upper layers.
|
||||
* \param[out] stat_tx_data_pdu Number of transmitted data PDUs to lower layers.
|
||||
* \param[out] stat_tx_data_bytes Number of transmitted data bytes to lower layers.
|
||||
* \param[out] stat_tx_retransmit_pdu_by_status Number of re-transmitted data PDUs due to status reception.
|
||||
* \param[out] stat_tx_retransmit_bytes_by_status Number of re-transmitted data bytes due to status reception.
|
||||
* \param[out] stat_tx_retransmit_pdu Number of re-transmitted data PDUs to lower layers.
|
||||
* \param[out] stat_tx_retransmit_bytes Number of re-transmitted data bytes to lower layers.
|
||||
* \param[out] stat_tx_control_pdu Number of transmitted control PDUs to lower layers.
|
||||
* \param[out] stat_tx_control_bytes Number of transmitted control bytes to lower layers.
|
||||
* \param[out] stat_rx_pdcp_sdu Number of SDUs delivered to upper layers.
|
||||
* \param[out] stat_rx_pdcp_bytes Number of bytes delivered to upper layers.
|
||||
* \param[out] stat_rx_data_pdus_duplicate Number of duplicate PDUs received.
|
||||
* \param[out] stat_rx_data_bytes_duplicate Number of duplicate bytes received.
|
||||
* \param[out] stat_rx_data_pdu Number of received PDUs from lower layers.
|
||||
* \param[out] stat_rx_data_bytes Number of received bytes from lower layers.
|
||||
* \param[out] stat_rx_data_pdu_dropped Number of received PDUs from lower layers, then dropped.
|
||||
* \param[out] stat_rx_data_bytes_dropped Number of received bytes from lower layers, then dropped.
|
||||
* \param[out] stat_rx_data_pdu_out_of_window Number of data PDUs received out of the receive window.
|
||||
* \param[out] stat_rx_data_bytes_out_of_window Number of data bytes received out of the receive window.
|
||||
* \param[out] stat_rx_control_pdu Number of control PDUs received.
|
||||
* \param[out] stat_rx_control_bytes Number of control bytes received.
|
||||
* \param[out] stat_timer_reordering_timed_out Number of times the timer "reordering" has timed-out.
|
||||
* \param[out] stat_timer_poll_retransmit_timed_out Number of times the timer "poll_retransmit" has timed-out.
|
||||
* \param[out] stat_timer_status_prohibit_timed_out Number of times the timer "status_prohibit" has timed-out.
|
||||
*/
|
||||
void rlc_am_stat_req (
|
||||
const protocol_ctxt_t* const ctxtP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
unsigned int* stat_tx_pdcp_sdu,
|
||||
unsigned int* stat_tx_pdcp_bytes,
|
||||
unsigned int* stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int* stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int* stat_tx_data_pdu,
|
||||
unsigned int* stat_tx_data_bytes,
|
||||
unsigned int* stat_tx_retransmit_pdu_by_status,
|
||||
unsigned int* stat_tx_retransmit_bytes_by_status,
|
||||
unsigned int* stat_tx_retransmit_pdu,
|
||||
unsigned int* stat_tx_retransmit_bytes,
|
||||
unsigned int* stat_tx_control_pdu,
|
||||
unsigned int* stat_tx_control_bytes,
|
||||
unsigned int* stat_rx_pdcp_sdu,
|
||||
unsigned int* stat_rx_pdcp_bytes,
|
||||
unsigned int* stat_rx_data_pdus_duplicate,
|
||||
unsigned int* stat_rx_data_bytes_duplicate,
|
||||
unsigned int* stat_rx_data_pdu,
|
||||
unsigned int* stat_rx_data_bytes,
|
||||
unsigned int* stat_rx_data_pdu_dropped,
|
||||
unsigned int* stat_rx_data_bytes_dropped,
|
||||
unsigned int* stat_rx_data_pdu_out_of_window,
|
||||
unsigned int* stat_rx_data_bytes_out_of_window,
|
||||
unsigned int* stat_rx_control_pdu,
|
||||
unsigned int* stat_rx_control_bytes,
|
||||
unsigned int* stat_timer_reordering_timed_out,
|
||||
unsigned int* stat_timer_poll_retransmit_timed_out,
|
||||
unsigned int* stat_timer_status_prohibit_timed_out);
|
||||
|
||||
/*! \fn void rlc_am_get_pdus (const protocol_ctxt_t* const ctxtP, void * const rlc_pP)
|
||||
* \brief Request the segmentation of SDUs based on status previously sent by MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void
|
||||
rlc_am_get_pdus (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP
|
||||
);
|
||||
|
||||
/*! \fn void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indication)
|
||||
* \brief Process the received PDUs from lower layer.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] data_indication PDUs from MAC.
|
||||
*/
|
||||
void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind);
|
||||
|
||||
/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP)
|
||||
* \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU.
|
||||
* \param[in] enb_flagP eNB or UE flag indication.
|
||||
* \return The maximum number of bytes that can be served by RLC instance to MAC.
|
||||
*/
|
||||
struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP);
|
||||
|
||||
/*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP)
|
||||
* \brief Gives PDUs to lower layer MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] enb_flagP eNB or UE flag
|
||||
* \return A PDU of the previously requested number of bytes, and the updated maximum number of bytes that can be served by RLC instance to MAC for next RLC transmission.
|
||||
*/
|
||||
struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP);
|
||||
|
||||
/*! \fn void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP)
|
||||
* \brief Receive PDUs from lower layer MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] data_indP PDUs from MAC.
|
||||
*/
|
||||
void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP);
|
||||
|
||||
/*! \fn uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP)
|
||||
* \brief Get Tx Buffer Occupancy.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
uint32_t rlc_am_get_buffer_occupancy_in_bytes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_data_req (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, mem_block_t *sduP)
|
||||
* \brief Interface with higher layers, buffer higher layer SDUS for transmission.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] sduP SDU. (A struct rlc_am_data_req is mapped on sduP->data.)
|
||||
*/
|
||||
void rlc_am_data_req (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, mem_block_t *sduP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_constants.h
|
||||
* \brief This file defines constant values used in RLC AM.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_CONSTANT_H__
|
||||
# define __RLC_AM_CONSTANT_H__
|
||||
|
||||
/** The sequence numbering modulo (10 bits). */
|
||||
# define RLC_AM_SN_MODULO 1024
|
||||
|
||||
/** The sequence numbering binary mask (10 bits). */
|
||||
# define RLC_AM_SN_MASK 0x3FF
|
||||
|
||||
/** FROM Spec: This constant is used by both the transmitting side and the receiving side of each AM RLC entity to calculate VT(MS) from VT(A), and VR(MR) from VR(R). AM_Window_Size = 512.. */
|
||||
# define RLC_AM_WINDOW_SIZE 512
|
||||
|
||||
/** Max number of bytes of incoming SDUs from upper layer that can be buffered in a RLC AM protocol instance. */
|
||||
# define RLC_AM_SDU_DATA_BUFFER_SIZE 64*1024
|
||||
|
||||
/** Max number of incoming SDUs from upper layer that can be buffered in a RLC AM protocol instance. */
|
||||
# define RLC_AM_SDU_CONTROL_BUFFER_SIZE 1024
|
||||
|
||||
/** Size of the retransmission buffer (number of PDUs). */
|
||||
# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_WINDOW_SIZE
|
||||
|
||||
/** PDU minimal header size in bytes. */
|
||||
# define RLC_AM_HEADER_MIN_SIZE 2
|
||||
|
||||
/** PDU Segment minimal header size in bytes = PDU header + SOStart + SOEnd. */
|
||||
# define RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE 4
|
||||
|
||||
/** If we want to send a segment of a PDU, then the min transport block size requested by MAC should be this amount. */
|
||||
# define RLC_AM_MIN_SEGMENT_SIZE_REQUEST 8
|
||||
|
||||
/** Max SDUs that can fit in a PDU. */
|
||||
# define RLC_AM_MAX_SDU_IN_PDU 128
|
||||
|
||||
/** Max fragments for a SDU. */
|
||||
# define RLC_AM_MAX_SDU_FRAGMENTS 32
|
||||
|
||||
/** Max Negative Acknowledgment SN (NACK_SN) fields in a STATUS PDU. */
|
||||
# define RLC_AM_MAX_NACK_IN_STATUS_PDU 1023
|
||||
|
||||
/** Max holes created by NACK_SN with segment offsets for a PDU in the retransmission buffer. */
|
||||
# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 16
|
||||
/** @} */
|
||||
|
||||
#define RLC_AM_POLL_PDU_INFINITE 0xFFFF
|
||||
#define RLC_AM_POLL_BYTE_INFINITE 0xFFFFFFFF
|
||||
|
||||
/* MACRO DEFINITIONS */
|
||||
|
||||
#define RLC_AM_NEXT_SN(sn) (((sn)+1) & (RLC_AM_SN_MASK))
|
||||
#define RLC_AM_PREV_SN(sn) (((sn)+(RLC_AM_SN_MODULO)-1) & (RLC_AM_SN_MASK))
|
||||
|
||||
#define RLC_DIFF_SN(sn,snref,modulus) ((sn+(modulus)-snref) & ((modulus)-1))
|
||||
#define RLC_SN_IN_WINDOW(sn,snref,modulus) ((RLC_DIFF_SN(sn,snref,modulus)) < ((modulus) >> 1))
|
||||
|
||||
#define RLC_AM_DIFF_SN(sn,snref) (RLC_DIFF_SN(sn,snref,RLC_AM_SN_MODULO))
|
||||
#define RLC_AM_SN_IN_WINDOW(sn,snref) (RLC_SN_IN_WINDOW(sn,snref,RLC_AM_SN_MODULO))
|
||||
|
||||
#define RLC_SET_BIT(x,offset) ((x) |= (1 << (offset)))
|
||||
#define RLC_GET_BIT(x,offset) (((x) & (1 << (offset))) >> (offset))
|
||||
#define RLC_CLEAR_BIT(x,offset) ((x) &= ~(1 << (offset)))
|
||||
|
||||
#define RLC_SET_EVENT(x,event) ((x) |= (event))
|
||||
#define RLC_GET_EVENT(x,event) ((x) & (event))
|
||||
#define RLC_CLEAR_EVENT(x,event) ((x) &= (~(event)))
|
||||
|
||||
/* Common to Data and Status PDU */
|
||||
#define RLC_AM_SN_BITS 10
|
||||
#define RLC_AM_PDU_D_C_BITS 1
|
||||
#define RLC_AM_PDU_E_BITS 1
|
||||
#define RLC_AM_PDU_FI_BITS 2
|
||||
#define RLC_AM_PDU_POLL_BITS 1
|
||||
#define RLC_AM_PDU_RF_BITS 1
|
||||
|
||||
|
||||
#define RLC_AM_LI_BITS 11
|
||||
#define RLC_AM_LI_MASK 0x7FF
|
||||
|
||||
|
||||
/* AM Data PDU */
|
||||
#define RLC_AM_PDU_E_OFFSET 2
|
||||
#define RLC_AM_PDU_FI_OFFSET (RLC_AM_PDU_E_OFFSET + RLC_AM_PDU_E_BITS)
|
||||
#define RLC_AM_PDU_POLL_OFFSET (RLC_AM_PDU_FI_OFFSET + RLC_AM_PDU_FI_BITS)
|
||||
#define RLC_AM_PDU_RF_OFFSET (RLC_AM_PDU_POLL_OFFSET + RLC_AM_PDU_POLL_BITS)
|
||||
#define RLC_AM_PDU_D_C_OFFSET (RLC_AM_PDU_RF_OFFSET + RLC_AM_PDU_RF_BITS)
|
||||
|
||||
#define RLC_AM_PDU_GET_FI_START(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET + 1))
|
||||
#define RLC_AM_PDU_GET_FI_END(px) (RLC_GET_BIT((px),RLC_AM_PDU_FI_OFFSET))
|
||||
|
||||
#define RLC_AM_PDU_GET_LI(x,offset) (((x) >> (offset)) & RLC_AM_LI_MASK)
|
||||
#define RLC_AM_PDU_SET_LI(x,li,offset) ((x) |= (((li) & RLC_AM_LI_MASK) << (offset)))
|
||||
|
||||
#define RLC_AM_PDU_SET_E(px) (RLC_SET_BIT((px),RLC_AM_PDU_E_OFFSET))
|
||||
#define RLC_AM_PDU_SET_D_C(px) (RLC_SET_BIT((px),RLC_AM_PDU_D_C_OFFSET))
|
||||
#define RLC_AM_PDU_SET_RF(px) (RLC_SET_BIT((px),RLC_AM_PDU_RF_OFFSET))
|
||||
#define RLC_AM_PDU_SET_POLL(px) (RLC_SET_BIT((px),RLC_AM_PDU_POLL_OFFSET))
|
||||
#define RLC_AM_PDU_CLEAR_POLL(px) (RLC_CLEAR_BIT((px),RLC_AM_PDU_POLL_OFFSET))
|
||||
|
||||
#define RLC_AM_PDU_SEGMENT_SO_LENGTH 15
|
||||
#define RLC_AM_PDU_SEGMENT_SO_BYTES 2
|
||||
#define RLC_AM_PDU_SEGMENT_SO_OFFSET 0
|
||||
#define RLC_AM_PDU_LSF_OFFSET (RLC_AM_PDU_SEGMENT_SO_OFFSET + RLC_AM_PDU_SEGMENT_SO_LENGTH)
|
||||
|
||||
#define RLC_AM_PDU_SET_LSF(px) (RLC_SET_BIT((px),RLC_AM_PDU_LSF_OFFSET))
|
||||
|
||||
#define RLC_AM_HEADER_LI_LENGTH(li) ((li) + ((li)>>1) + ((li)&1))
|
||||
#define RLC_AM_PDU_SEGMENT_HEADER_SIZE(numLis) (RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + RLC_AM_HEADER_LI_LENGTH(numLis))
|
||||
|
||||
/* STATUS PDU */
|
||||
#define RLC_AM_STATUS_PDU_CPT_STATUS 0
|
||||
|
||||
#define RLC_AM_STATUS_PDU_CPT_OFFSET 4
|
||||
#define RLC_AM_STATUS_PDU_CPT_LENGTH 3
|
||||
|
||||
#define RLC_AM_STATUS_PDU_ACK_SN_OFFSET 2
|
||||
|
||||
#define RLC_AM_STATUS_PDU_SO_LENGTH 15
|
||||
|
||||
#define RLC_AM_STATUS_PDU_SO_END_ALL_BYTES 0x7FFF
|
||||
|
||||
|
||||
/* Uplink STATUS PDU trigger events */
|
||||
#define RLC_AM_STATUS_NOT_TRIGGERED 0
|
||||
#define RLC_AM_STATUS_TRIGGERED_POLL 0x01 /* Status Report is triggered by a received poll */
|
||||
#define RLC_AM_STATUS_TRIGGERED_T_REORDERING 0x02 /* Status Report is triggered by Timer Reordering Expiry */
|
||||
#define RLC_AM_STATUS_TRIGGERED_DELAYED 0x10 /* Status is delayed until SN(receivedPoll) < VR(MS) */
|
||||
#define RLC_AM_STATUS_PROHIBIT 0x20 /* TimerStatusProhibit still running */
|
||||
#define RLC_AM_STATUS_NO_TX_MASK (RLC_AM_STATUS_PROHIBIT | RLC_AM_STATUS_TRIGGERED_DELAYED)
|
||||
|
||||
/* Status triggered (bit 5-7) will be concatenated with Poll triggered (bit 0-4) for RLCdec. RLC_AM_STATUS_TRIGGERED_DELAYED is not recorded. */
|
||||
#define RLC_AM_SET_STATUS(x,event) (RLC_SET_EVENT(x,event))
|
||||
#define RLC_AM_GET_STATUS(x,event) (RLC_GET_EVENT(x,event))
|
||||
#define RLC_AM_CLEAR_STATUS(x,event) (RLC_CLEAR_EVENT(x,event))
|
||||
#define RLC_AM_CLEAR_ALL_STATUS(x) ((x) = (RLC_AM_STATUS_NOT_TRIGGERED))
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_entity.h
|
||||
* \brief This file defines the RLC AM variables stored in a struct called rlc_am_entity_t.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note The rlc_am_entity_t structure store protocol variables, statistic variables, allocation variables, buffers and other miscellaneous variables.
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_impl_ RLC AM Layer Internal Reference Implementation
|
||||
* @ingroup _rlc_am_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
# ifndef __RLC_AM_ENTITY_H__
|
||||
# define __RLC_AM_ENTITY_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include <pthread.h>
|
||||
# include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
# include "list.h"
|
||||
# include "rlc_primitives.h"
|
||||
# include "rlc_def_lte.h"
|
||||
# include "rlc_def.h"
|
||||
# include "rlc_am_structs.h"
|
||||
# include "rlc_am_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \struct rlc_am_entity_t
|
||||
* \brief Structure containing a RLC AM instance protocol variables, statistic variables, allocation variables, buffers and other miscellaneous variables.
|
||||
*/
|
||||
typedef struct rlc_am_entity_s {
|
||||
|
||||
|
||||
rb_id_t rb_id; /*!< \brief Radio bearer identifier, for statistics and trace purpose. */
|
||||
logical_chan_id_t channel_id; /*!< \brief Transport channel identifier. */
|
||||
bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */
|
||||
|
||||
rlc_buffer_occupancy_t sdu_buffer_occupancy; /*!< \brief Number of bytes of unsegmented SDUs. */
|
||||
rlc_buffer_occupancy_t status_buffer_occupancy; /*!< \brief Number of bytes of control PDUs waiting for transmission. */
|
||||
|
||||
rlc_am_control_pdu_info_t control_pdu_info;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// TX BUFFERS
|
||||
//---------------------------------------------------------------------
|
||||
//pthread_spinlock_t lock_input_sdus;
|
||||
pthread_mutex_t lock_input_sdus;
|
||||
rlc_am_tx_sdu_management_t *input_sdus; /*!< \brief Input SDU buffer (for SDUs coming from upper layers). */
|
||||
signed int nb_sdu; /*!< \brief Total number of valid rlc_am_tx_sdu_management_t in input_sdus[]. */
|
||||
signed int nb_sdu_no_segmented; /*!< \brief Total number of SDUs not segmented and partially segmented. nb_sdu_no_segmented = next_sdu_index - current_sdu_index */
|
||||
signed int next_sdu_index; /*!< \brief Next SDU index in input_sdus array where for a new incoming SDU. */
|
||||
signed int current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented which is not segmented or partially segmented. */
|
||||
|
||||
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer; /*!< \brief Transmission PDU data buffer. Used also for retransmissions */
|
||||
signed int retrans_num_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */
|
||||
signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. Only payload is taken into account */
|
||||
bool force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// RX BUFFERS
|
||||
//---------------------------------------------------------------------
|
||||
list2_t receiver_buffer; /*!< \brief Receiver buffer implemented with a list. */
|
||||
mem_block_t *output_sdu_in_construction; /*!< \brief Memory area where a complete SDU is reassemblied before being send to upper layers. */
|
||||
sdu_size_t output_sdu_size_to_write; /*!< \brief Size of the reassemblied SDU. */
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// PROTOCOL VARIABLES
|
||||
//---------------------------------------------------------------------
|
||||
rlc_protocol_state_t protocol_state; /*!< \brief Protocol state, can be RLC_NULL_STATE, RLC_DATA_TRANSFER_READY_STATE. */
|
||||
//-----------------------------
|
||||
// TX STATE VARIABLES
|
||||
//-----------------------------
|
||||
rlc_usn_t
|
||||
vt_a; /*!< \brief Acknowledgement state variable. This state variable holds the value of the SN of the next AMD PDU for which a positive acknowledgment is to be received in-sequence, and it serves as the lower edge of the transmitting window. It is initially set to 0, and is updated whenever the AM RLC entity receives a positive acknowledgment for an AMD PDU with SN = VT(A).*/
|
||||
rlc_usn_t vt_ms; /*!< \brief Maximum send state variable. This state variable equals VT(A) + AM_Window_Size, and it serves as the higher edge of the transmitting window. */
|
||||
rlc_usn_t
|
||||
vt_s; /*!< \brief Send state variable. This state variable holds the value of the SN to be assigned for the next newly generated AMD PDU. It is initially set to 0, and is updated whenever the AM RLC entity delivers an AMD PDU with SN = VT(S).*/
|
||||
rlc_usn_t
|
||||
poll_sn; /*!< \brief Poll send state variable. This state variable holds the value of VT(S)-1 upon the most recent transmission of a RLC data PDU with the poll bit set to “1”. It is initially set to 0.*/
|
||||
|
||||
//-----------------------------
|
||||
// RX STATE VARIABLES
|
||||
//-----------------------------
|
||||
rlc_usn_t
|
||||
vr_r; /*!< \brief Receive state variable. This state variable holds the value of the SN following the last in-sequence completely received AMD PDU, and it serves as the lower edge of the receiving window. It is initially set to 0, and is updated whenever the AM RLC entity receives an AMD PDU with SN = VR(R). */
|
||||
rlc_usn_t
|
||||
vr_mr; /*!< \brief Maximum acceptable receive state variable. This state variable equals VR(R) + AM_Window_Size, and it holds the value of the SN of the first AMD PDU that is beyond the receiving window and serves as the higher edge of the receiving window. */
|
||||
rlc_usn_t vr_x; /*!< \brief t-Reordering state variable. This state variable holds the value of the SN following the SN of the RLC data PDU which triggered t-Reordering. */
|
||||
rlc_usn_t
|
||||
vr_ms; /*!< \brief Maximum STATUS transmit state variable. This state variable holds the highest possible value of the SN which can be indicated by “ACK_SN” when a STATUS PDU needs to be constructed. It is initially set to 0. */
|
||||
rlc_usn_t
|
||||
vr_h; /*!< \brief Highest received state variable. This state variable holds the value of the SN following the SN of the RLC data PDU with the highest SN among received RLC data PDUs. It is initially set to 0. */
|
||||
|
||||
//-----------------------------
|
||||
// TIMERS CONFIGURED BY RRC
|
||||
//-----------------------------
|
||||
rlc_am_timer_t t_poll_retransmit; /*!< \brief This timer is used by the transmitting side of an AM RLC entity in order to retransmit a poll. */
|
||||
rlc_am_timer_t
|
||||
t_reordering; /*!< \brief This timer is used by the receiving side of an AM RLC entity and receiving UM RLC entity in order to detect loss of RLC PDUs at lower layer (see sub clauses 5.1.2.2 and 5.1.3.2). If t-Reordering is running, t-Reordering shall not be started additionally, i.e. only one t-Reordering per RLC entity is running at a given time. */
|
||||
rlc_am_timer_t t_status_prohibit; /*!< \brief This timer is used by the receiving side of an AM RLC entity in order to prohibit transmission of a STATUS PDU. */
|
||||
|
||||
//-----------------------------
|
||||
// COUNTERS
|
||||
//-----------------------------
|
||||
unsigned int c_pdu_without_poll; /*!< \brief This counter is initially set to 0. It counts the number of AMD PDUs sent since the most recent poll bit was transmitted. */
|
||||
unsigned int c_byte_without_poll;/*!< \brief This counter is initially set to 0. It counts the number of data bytes sent since the most recent poll bit was transmitted. */
|
||||
|
||||
//-----------------------------
|
||||
// PARAMETERS CONFIGURED BY RRC
|
||||
//-----------------------------
|
||||
uint16_t max_retx_threshold; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to limit the number of retransmissions of an AMD PDU. */
|
||||
uint16_t poll_pdu; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollPDU PDUs. */
|
||||
uint32_t poll_byte; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// STATISTICS
|
||||
//---------------------------------------------------------------------
|
||||
unsigned int stat_tx_pdcp_sdu; /*!< \brief Number of SDUs received from upper layers. */
|
||||
unsigned int stat_tx_pdcp_bytes; /*!< \brief Number of SDU bytes received from upper layers. */
|
||||
unsigned int stat_tx_pdcp_sdu_discarded; /*!< \brief Number of SDUs received from upper layers that have been discarded. */
|
||||
unsigned int stat_tx_pdcp_bytes_discarded; /*!< \brief Number of SDU bytes received from upper layers that have been discarded. */
|
||||
|
||||
unsigned int stat_tx_data_pdu; /*!< \brief For statistic report, number of transmitted PDUs to lower layers. */
|
||||
unsigned int stat_tx_data_bytes; /*!< \brief For statistic report, number of transmitted bytes to lower layers. */
|
||||
unsigned int stat_tx_retransmit_pdu_by_status; /*!< \brief Not updated. */
|
||||
unsigned int stat_tx_retransmit_bytes_by_status; /*!< \brief Not updated. */
|
||||
unsigned int stat_tx_retransmit_pdu; /*!< \brief Not updated. */
|
||||
unsigned int stat_tx_retransmit_bytes; /*!< \brief Not updated. */
|
||||
unsigned int stat_tx_control_pdu; /*!< \brief Not updated. */
|
||||
unsigned int stat_tx_control_bytes; /*!< \brief Not updated. */
|
||||
|
||||
unsigned int stat_rx_pdcp_sdu; /*!< \brief For statistic report, number of reassemblied SDUs, sent to upper layers. */
|
||||
unsigned int stat_rx_pdcp_bytes; /*!< \brief For statistic report, number of reassemblied bytes, sent to upper layers. */
|
||||
unsigned int stat_rx_data_pdus_duplicate; /*!< \brief For statistic report, number of received duplicated PDUs from lower layers. */
|
||||
unsigned int stat_rx_data_bytes_duplicate; /*!< \brief For statistic report, number of received duplicated bytes from lower layers. */
|
||||
unsigned int stat_rx_data_pdu; /*!< \brief For statistic report, number of received PDUs from lower layers. */
|
||||
unsigned int stat_rx_data_bytes; /*!< \brief For statistic report, number of received bytes from lower layers. */
|
||||
unsigned int stat_rx_data_pdu_dropped; /*!< \brief For statistic report, number of dropped received PDUs from lower layers. Does not include out of window stat. */
|
||||
unsigned int stat_rx_data_bytes_dropped; /*!< \brief For statistic report, number of dropped received bytes from lower layers. Does not include out of window stat. */
|
||||
unsigned int stat_rx_data_pdu_out_of_window; /*!< \brief Number of data PDUs received out of the receive window. */
|
||||
unsigned int stat_rx_data_bytes_out_of_window; /*!< \brief Number of data bytes received out of the receive window. */
|
||||
unsigned int stat_rx_control_pdu; /*!< \brief Number of control PDUs received. */
|
||||
unsigned int stat_rx_control_bytes; /*!< \brief Number of control bytes received. */
|
||||
|
||||
unsigned int stat_timer_reordering_timed_out;
|
||||
unsigned int stat_timer_poll_retransmit_timed_out;
|
||||
unsigned int stat_timer_status_prohibit_timed_out;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// OUTPUTS
|
||||
//---------------------------------------------------------------------
|
||||
sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of remaining bytes available for transmission of any RLC PDU indicated by lower layer */
|
||||
list_t pdus_to_mac_layer; /*!< \brief PDUs buffered for transmission to MAC layer. */
|
||||
list_t control_pdu_list; /*!< \brief Control PDUs buffered for transmission to MAC layer. */
|
||||
list_t segmentation_pdu_list; /*!< \brief List of "freshly" segmented PDUs. */
|
||||
|
||||
uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */
|
||||
rlc_sn_t sn_status_triggered_delayed; /*!< \brief SN of the last received poll for which Status is delayed until SN is out of Rx Window. */
|
||||
uint32_t last_absolute_subframe_status_indication; /*!< \brief The last absolute subframe number a MAC status indication has been received by RLC. */
|
||||
//-----------------------------
|
||||
// buffer occupancy measurements sent to MAC
|
||||
//-----------------------------
|
||||
// note occupancy of other buffers is deducted from nb elements in lists
|
||||
rlc_buffer_occupancy_t buffer_occupancy_retransmission_buffer; /*!< \brief Number of PDUs. */
|
||||
|
||||
bool initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */
|
||||
bool configured; /*!< \brief Boolean for rlc_am_entity_t struct configuration. */
|
||||
} rlc_am_entity_t;
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
rlc_am_in_sdu.c -
|
||||
-------------------
|
||||
AUTHOR : Lionel GAUTHIER
|
||||
COMPANY : EURECOM
|
||||
EMAIL : Lionel.Gauthier@eurecom.fr
|
||||
***************************************************************************/
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_IN_SDU_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#define TRACE_RLC_AM_FREE_SDU 0
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_free_in_sdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const unsigned int index_in_bufferP)
|
||||
{
|
||||
if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) {
|
||||
/* BugFix: SDU shall have been already freed during initial PDU segmentation or concatenation !! */
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.761
|
||||
if(rlcP->input_sdus[index_in_bufferP].mem_block != NULL)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Tx SDU Conf: Data Part is not empty index=%d LcId=%d\n",
|
||||
index_in_bufferP,rlcP->channel_id);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
AssertFatal(rlcP->input_sdus[index_in_bufferP].mem_block == NULL, "RLC AM Tx SDU Conf: Data Part is not empty index=%d LcId=%d\n",
|
||||
index_in_bufferP,rlcP->channel_id);
|
||||
*/
|
||||
/*
|
||||
if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) {
|
||||
free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__);
|
||||
rlcP->input_sdus[index_in_bufferP].mem_block = NULL;
|
||||
rlcP->nb_sdu_no_segmented -= 1;
|
||||
rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
rlcP->nb_sdu -= 1;
|
||||
memset(&rlcP->input_sdus[index_in_bufferP], 0, sizeof(rlc_am_tx_sdu_management_t));
|
||||
rlcP->input_sdus[index_in_bufferP].flags.transmitted_successfully = 1;
|
||||
|
||||
// case when either one SDU needs to be removed from segmentation or SDU buffer is full
|
||||
if (rlcP->current_sdu_index == index_in_bufferP) {
|
||||
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// wrapping and reset current_sdu_index to next_sdu_index when all transmitted SDUs have been acknowledged
|
||||
while ((rlcP->current_sdu_index != rlcP->next_sdu_index) &&
|
||||
(rlcP->input_sdus[rlcP->current_sdu_index].flags.transmitted_successfully == 1)) {
|
||||
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
#if TRACE_RLC_AM_FREE_SDU
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[FREE SDU] SDU INDEX %03u current_sdu_index=%u next_sdu_index=%u nb_sdu_no_segmented=%u\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlcP),
|
||||
index_in_bufferP,
|
||||
rlcP->current_sdu_index,
|
||||
rlcP->next_sdu_index,
|
||||
rlcP->nb_sdu_no_segmented);
|
||||
#endif
|
||||
}
|
||||
// called when segmentation is done
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_free_in_sdu_data(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlcP,
|
||||
const unsigned int index_in_bufferP)
|
||||
{
|
||||
if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) {
|
||||
if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) {
|
||||
free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__);
|
||||
rlcP->input_sdus[index_in_bufferP].mem_block = NULL;
|
||||
rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0;
|
||||
rlcP->nb_sdu_no_segmented -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_in_sdu_is_empty(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP)
|
||||
{
|
||||
if (rlcP->nb_sdu == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// called when PDU is ACKED
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_pdu_sdu_data_cnf(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
int pdu_sdu_index;
|
||||
int sdu_index;
|
||||
|
||||
for (pdu_sdu_index = 0; pdu_sdu_index < rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].nb_sdus; pdu_sdu_index++) {
|
||||
sdu_index = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].sdus_index[pdu_sdu_index];
|
||||
//assert(sdu_index >= 0);
|
||||
//assert(sdu_index < RLC_AM_SDU_CONTROL_BUFFER_SIZE);
|
||||
if(sdu_index < 0 || sdu_index >= RLC_AM_SDU_CONTROL_BUFFER_SIZE) {
|
||||
LOG_E(RLC, "sdu_index error. sdu_index %d, pdu_sdu_index %d\n", sdu_index, pdu_sdu_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
rlc_pP->input_sdus[sdu_index].nb_pdus_ack += 1;
|
||||
|
||||
if ((rlc_pP->input_sdus[sdu_index].nb_pdus_ack == rlc_pP->input_sdus[sdu_index].nb_pdus) &&
|
||||
(rlc_pP->input_sdus[sdu_index].sdu_remaining_size == 0)) {
|
||||
#if TEST_RLC_AM
|
||||
rlc_am_v9_3_0_test_data_conf (
|
||||
rlc_pP->module_id,
|
||||
rlc_pP->rb_id,
|
||||
rlc_pP->input_sdus[sdu_index].mui,
|
||||
RLC_SDU_CONFIRM_YES);
|
||||
#else
|
||||
rlc_data_conf(
|
||||
ctxt_pP,
|
||||
rlc_pP->rb_id,
|
||||
rlc_pP->input_sdus[sdu_index].mui,
|
||||
RLC_SDU_CONFIRM_YES,
|
||||
rlc_pP->is_data_plane);
|
||||
#endif
|
||||
rlc_am_free_in_sdu(ctxt_pP, rlc_pP, sdu_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_in_sdu.h
|
||||
* \brief This file defines the prototypes of the utility functions manipulating the incoming SDU buffer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_input_sdu_impl_ RLC AM Input SDU buffer Internal Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_AM_IN_SDU_H__
|
||||
# define __RLC_AM_IN_SDU_H__
|
||||
/*! \fn void rlc_am_free_in_sdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, unsigned int index_in_bufferP)
|
||||
* \brief Free a higher layer SDU stored in input_sdus[] buffer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] index_in_bufferP Position index of the SDU.
|
||||
* \note Update also the RLC AM instance variables nb_sdu, current_sdu_index, nb_sdu_no_segmented.
|
||||
*/
|
||||
void rlc_am_free_in_sdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, unsigned int index_in_bufferP);
|
||||
|
||||
|
||||
/*! \fn void rlc_am_free_in_sdu_data (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, unsigned int index_in_bufferP)
|
||||
* \brief Free a higher layer SDU data part, the SDU is stored in input_sdus[] buffer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] index_in_bufferP Position index of the SDU.
|
||||
* \note This procedure is called when the SDU segmentation is done for this SDU. Update also the RLC AM instance variable nb_sdu_no_segmented.
|
||||
*/
|
||||
void rlc_am_free_in_sdu_data (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, unsigned int index_in_bufferP);
|
||||
|
||||
|
||||
/*! \fn signed int rlc_am_in_sdu_is_empty(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP)
|
||||
* \brief Indicates if the input SDU buffer for incoming higher layer SDUs is empty or not.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \return 1 if the buffer is empty, else 0.
|
||||
*/
|
||||
signed int rlc_am_in_sdu_is_empty(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP);
|
||||
|
||||
/*! \fn void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP)
|
||||
* \brief Process SDU cnf of a ACKED PDU for all SDUs concatenated in this PDU.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of the PDU.
|
||||
*/
|
||||
void rlc_am_pdu_sdu_data_cnf(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,const rlc_sn_t snP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,263 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_INIT_C 1
|
||||
#include <string.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_init(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP)
|
||||
{
|
||||
if (rlc_pP->initialized == true) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] INITIALIZATION ALREADY DONE, DOING NOTHING\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] INITIALIZATION: STATE VARIABLES, BUFFERS, LISTS\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
memset(rlc_pP, 0, sizeof(rlc_am_entity_t));
|
||||
|
||||
list2_init(&rlc_pP->receiver_buffer, "RX BUFFER");
|
||||
list_init(&rlc_pP->pdus_to_mac_layer, "PDUS TO MAC");
|
||||
list_init(&rlc_pP->control_pdu_list, "CONTROL PDU LIST");
|
||||
list_init(&rlc_pP->segmentation_pdu_list, "SEGMENTATION PDU LIST");
|
||||
//LOG_D(RLC,"RLC_AM_SDU_CONTROL_BUFFER_SIZE %d sizeof(rlc_am_tx_sdu_management_t) %d \n", RLC_AM_SDU_CONTROL_BUFFER_SIZE, sizeof(rlc_am_tx_sdu_management_t));
|
||||
|
||||
pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL);
|
||||
rlc_pP->input_sdus = calloc(1, RLC_AM_SDU_CONTROL_BUFFER_SIZE*sizeof(rlc_am_tx_sdu_management_t));
|
||||
//#warning "cast the rlc retrans buffer to uint32"
|
||||
// rlc_pP->tx_data_pdu_buffer = calloc(1, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
|
||||
rlc_pP->tx_data_pdu_buffer = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(
|
||||
rlc_am_tx_data_pdu_management_t)));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] input_sdus[] = %p element size=%zu\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->input_sdus,
|
||||
sizeof(rlc_am_tx_sdu_management_t));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] tx_data_pdu_buffer[] = %p element size=%zu\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->tx_data_pdu_buffer,
|
||||
sizeof(rlc_am_tx_data_pdu_management_t));
|
||||
|
||||
// TX state variables
|
||||
//rlc_pP->vt_a = 0;
|
||||
rlc_pP->vt_ms = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
|
||||
//rlc_pP->vt_s = 0;
|
||||
//rlc_pP->poll_sn = 0;
|
||||
// TX counters
|
||||
//rlc_pP->c_pdu_without_poll = 0;
|
||||
//rlc_pP->c_byte_without_poll = 0;
|
||||
// RX state variables
|
||||
//rlc_pP->vr_r = 0;
|
||||
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
|
||||
rlc_pP->vr_x = RLC_SN_UNDEFINED;
|
||||
//rlc_pP->vr_ms = 0;
|
||||
//rlc_pP->vr_h = 0;
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
|
||||
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
|
||||
|
||||
rlc_pP->initialized = true;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_reestablish(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP)
|
||||
{
|
||||
/*
|
||||
* RLC re-establishment is performed upon request by RRC, and the function
|
||||
* is applicable for AM, UM and TM RLC entities.
|
||||
* When RRC indicates that an RLC entity should be re-established, the RLC entity shall:
|
||||
* - if it is an AM RLC entity:
|
||||
* - when possible, reassemble RLC SDUs from any byte segments of AMD PDUs with SN < VR(MR) in the
|
||||
* receiving side, remove RLC headers when doing so and deliver all reassembled RLC SDUs to upper layer in
|
||||
* ascending order of the RLC SN, if not delivered before;
|
||||
* - discard the remaining AMD PDUs and byte segments of AMD PDUs in the receiving side;
|
||||
* - discard all RLC SDUs and AMD PDUs in the transmitting side;
|
||||
* - discard all RLC control PDUs.
|
||||
* - stop and reset all timers;
|
||||
* - reset all state variables to their initial values.
|
||||
*/
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM REESTABLISH] RE-INIT STATE VARIABLES, BUFFERS, LISTS\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
//#warning TODO when possible reassemble RLC SDUs from any byte segments of AMD PDUs with SN inf VR(MR)
|
||||
list2_free(&rlc_pP->receiver_buffer);
|
||||
|
||||
list_free(&rlc_pP->pdus_to_mac_layer);
|
||||
list_free(&rlc_pP->control_pdu_list);
|
||||
list_free(&rlc_pP->segmentation_pdu_list);
|
||||
|
||||
|
||||
// TX state variables
|
||||
rlc_pP->vt_a = 0;
|
||||
rlc_pP->vt_ms = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
|
||||
rlc_pP->vt_s = 0;
|
||||
rlc_pP->poll_sn = 0;
|
||||
|
||||
// TX counters
|
||||
rlc_pP->c_pdu_without_poll = 0;
|
||||
rlc_pP->c_byte_without_poll = 0;
|
||||
|
||||
// RX state variables
|
||||
rlc_pP->vr_r = 0;
|
||||
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
|
||||
rlc_pP->vr_x = RLC_SN_UNDEFINED;
|
||||
rlc_pP->vr_ms = 0;
|
||||
rlc_pP->vr_h = 0;
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
rlc_pP->status_requested = RLC_AM_STATUS_NOT_TRIGGERED;
|
||||
|
||||
rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
|
||||
|
||||
rlc_pP->initialized = true;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_cleanup(
|
||||
rlc_am_entity_t* const rlc_pP
|
||||
)
|
||||
{
|
||||
list2_free(&rlc_pP->receiver_buffer);
|
||||
list_free(&rlc_pP->pdus_to_mac_layer);
|
||||
list_free(&rlc_pP->control_pdu_list);
|
||||
list_free(&rlc_pP->segmentation_pdu_list);
|
||||
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction != NULL) {
|
||||
free_mem_block(rlc_pP->output_sdu_in_construction, __func__);
|
||||
rlc_pP->output_sdu_in_construction = NULL;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
|
||||
if (rlc_pP->input_sdus != NULL) {
|
||||
for (i=0; i < RLC_AM_SDU_CONTROL_BUFFER_SIZE; i++) {
|
||||
if (rlc_pP->input_sdus[i].mem_block != NULL) {
|
||||
free_mem_block(rlc_pP->input_sdus[i].mem_block, __func__);
|
||||
rlc_pP->input_sdus[i].mem_block = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(rlc_pP->input_sdus);
|
||||
rlc_pP->input_sdus = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&rlc_pP->lock_input_sdus);
|
||||
|
||||
if (rlc_pP->tx_data_pdu_buffer != NULL) {
|
||||
for (i=0; i < RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE; i++) {
|
||||
if (rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block != NULL) {
|
||||
free_mem_block(rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block, __func__);
|
||||
rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(rlc_pP->tx_data_pdu_buffer);
|
||||
rlc_pP->tx_data_pdu_buffer = NULL;
|
||||
}
|
||||
|
||||
memset(rlc_pP, 0, sizeof(rlc_am_entity_t));
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_configure(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const uint16_t max_retx_thresholdP,
|
||||
const uint16_t poll_pduP,
|
||||
const uint16_t poll_byteP,
|
||||
const uint32_t t_poll_retransmitP,
|
||||
const uint32_t t_reorderingP,
|
||||
const uint32_t t_status_prohibitP)
|
||||
{
|
||||
if (rlc_pP->configured == true) {
|
||||
LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RECONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
max_retx_thresholdP,
|
||||
poll_pduP,
|
||||
poll_byteP,
|
||||
t_poll_retransmitP,
|
||||
t_reorderingP,
|
||||
t_status_prohibitP);
|
||||
|
||||
rlc_pP->max_retx_threshold = max_retx_thresholdP;
|
||||
rlc_pP->poll_pdu = poll_pduP;
|
||||
rlc_pP->poll_byte = poll_byteP;
|
||||
rlc_pP->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
|
||||
rlc_pP->t_poll_retransmit.ms_duration = t_poll_retransmitP;
|
||||
rlc_pP->t_reordering.ms_duration = t_reorderingP;
|
||||
rlc_pP->t_status_prohibit.ms_duration = t_status_prohibitP;
|
||||
|
||||
} else {
|
||||
LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[CONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
max_retx_thresholdP,
|
||||
poll_pduP,
|
||||
poll_byteP,
|
||||
t_poll_retransmitP,
|
||||
t_reorderingP,
|
||||
t_status_prohibitP);
|
||||
|
||||
rlc_pP->max_retx_threshold = max_retx_thresholdP;
|
||||
rlc_pP->poll_pdu = poll_pduP;
|
||||
rlc_pP->poll_byte = poll_byteP;
|
||||
rlc_pP->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
|
||||
|
||||
|
||||
rlc_am_init_timer_poll_retransmit(ctxt_pP, rlc_pP, t_poll_retransmitP);
|
||||
rlc_am_init_timer_reordering (ctxt_pP, rlc_pP, t_reorderingP);
|
||||
rlc_am_init_timer_status_prohibit(ctxt_pP, rlc_pP, t_status_prohibitP);
|
||||
|
||||
rlc_pP->configured = true;
|
||||
}
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_set_debug_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP)
|
||||
{
|
||||
rlc_pP->rb_id = rb_idP;
|
||||
rlc_pP->channel_id = chan_idP;
|
||||
|
||||
if (srb_flagP) {
|
||||
rlc_pP->is_data_plane = 0;
|
||||
} else {
|
||||
rlc_pP->is_data_plane = 1;
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SET DEBUG INFOS]\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_init.h
|
||||
* \brief This file defines the prototypes of the functions initializing a RLC AM protocol instance.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_init_impl_ RLC AM Init Reference Implementation
|
||||
* @ingroup _rlc_am_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_INIT_H__
|
||||
# define __RLC_AM_INIT_H__
|
||||
|
||||
# include "UTIL/MEM/mem_block.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//#include "PHY/defs.h"
|
||||
|
||||
|
||||
/*! \struct rlc_am_info_t
|
||||
* \brief Structure containing RLC AM configuration parameters.
|
||||
*/
|
||||
typedef volatile struct {
|
||||
uint16_t max_retx_threshold; /*!< \brief Maximum number of retransmissions for one RLC AM PDU. */
|
||||
uint16_t poll_pdu; /*!< \brief Generate a status each poll_pdu pdu sent. */
|
||||
uint16_t poll_byte; /*!< \brief Generate a status each time poll_byte bytes have been sent. */
|
||||
uint32_t t_poll_retransmit; /*!< \brief t-PollRetransmit timer initial value. */
|
||||
uint32_t t_reordering; /*!< \brief t-Reordering timer initial value. */
|
||||
uint32_t t_status_prohibit; /*!< \brief t-StatusProhibit timer initial value. */
|
||||
} rlc_am_info_t;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn void rlc_am_init (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP)
|
||||
* \brief Initialize the RLC AM protocol instance, reset variables, allocate buffers, lists, then, the next step in order have a running RLC AM instance is to configure and set debug informations for this RLC instance.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_init (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t* rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_cleanup(rlc_am_entity_t *const rlc_pP)
|
||||
* \brief Free all memory resources allocated and kept by this RLC AM instance.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_cleanup(rlc_am_entity_t* rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_configure(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, uint16_t max_retx_thresholdP, uint16_t poll_pduP, uint16_t poll_byteP, uint32_t t_poll_retransmitP, uint32_t t_reorderingP, uint32_t t_status_prohibitP)
|
||||
* \brief Set RLC AM protocol parameters.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] max_retx_thresholdP Limit the number of retransmissions of an
|
||||
AMD PDU.
|
||||
* \param[in] poll_pduP Trigger a poll for every poll_pduP PDUs.
|
||||
* \param[in] poll_byteP Trigger a poll for every pollByte bytes.
|
||||
* \param[in] t_poll_retransmitP This timer is used by the transmitting side of an AM RLC entity in order to retransmit a poll, value in frames.
|
||||
* \param[in] t_reorderingP This timer is used by the receiving side of an AM RLC entity in order to detect loss of RLC PDUs at lower layer, value in frames.
|
||||
* \param[in] t_status_prohibitP This timer is used by the receiving side of an AM RLC entity in order to prohibit transmission of a STATUS PDU, value in frames.
|
||||
*/
|
||||
void rlc_am_configure(const protocol_ctxt_t* const ctxtP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
const uint16_t max_retx_thresholdP,
|
||||
const uint16_t poll_pduP,
|
||||
const uint16_t poll_byteP,
|
||||
const uint32_t t_poll_retransmitP,
|
||||
const uint32_t t_reorderingP,
|
||||
const uint32_t t_status_prohibitP);
|
||||
|
||||
|
||||
/*! \fn void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP)
|
||||
* \brief Set informations that will be displayed in traces, helping the debug process.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void rlc_am_set_debug_infos(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, const logical_chan_id_t chan_idP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_REASSEMBLY_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "assertions.h"
|
||||
#include "rlc.h"
|
||||
#include "rlc_am.h"
|
||||
#include "list.h"
|
||||
//#include "LAYER2/MAC/extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void
|
||||
rlc_am_clear_rx_sdu (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_reassembly (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
uint8_t *src_pP,
|
||||
const int32_t lengthP) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] reassembly() %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
lengthP);
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction == NULL) {
|
||||
rlc_pP->output_sdu_in_construction = get_free_mem_block (RLC_SDU_MAX_SIZE, __func__);
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
|
||||
//assert(rlc_pP->output_sdu_in_construction != NULL);
|
||||
if(rlc_pP->output_sdu_in_construction == NULL) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] output_sdu_in_construction is NULL\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction != NULL) {
|
||||
// check if no overflow in size
|
||||
if ((rlc_pP->output_sdu_size_to_write + lengthP) <= RLC_SDU_MAX_SIZE) {
|
||||
memcpy (&rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write], src_pP, lengthP);
|
||||
rlc_pP->output_sdu_size_to_write += lengthP;
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] ERROR SDU SIZE OVERFLOW SDU GARBAGED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#if STOP_ON_IP_TRAFFIC_OVERLOAD
|
||||
AssertFatal(0, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_IND, SDU SIZE OVERFLOW SDU GARBAGED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
// erase SDU
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PAYLOAD] ERROR OUTPUT SDU IS NULL\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#if STOP_ON_IP_TRAFFIC_OVERLOAD
|
||||
AssertFatal(0, PROTOCOL_RLC_AM_CTXT_FMT" RLC_AM_DATA_IND, SDU DROPPED, OUT OF MEMORY\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_send_sdu (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP) {
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND_SDU] %d bytes sdu %p\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
|
||||
if (rlc_pP->output_sdu_size_to_write > 0) {
|
||||
rlc_pP->stat_rx_pdcp_sdu += 1;
|
||||
rlc_pP->stat_rx_pdcp_bytes += rlc_pP->output_sdu_size_to_write;
|
||||
#if TEST_RLC_AM
|
||||
rlc_am_v9_3_0_test_data_ind (rlc_pP->module_id,
|
||||
rlc_pP->rb_id,
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
#else
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
char message_string[7000];
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", rlc_pP->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "SDU size : %u\n", rlc_pP->output_sdu_size_to_write);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < rlc_pP->output_sdu_size_to_write; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size],
|
||||
" %02x",
|
||||
rlc_pP->output_sdu_in_construction->data[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
LOG_T(RLC, "%s", message_string);
|
||||
}
|
||||
|
||||
#if !ENABLE_ITTI
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
#endif
|
||||
rlc_data_ind (ctxt_pP,
|
||||
BOOL_NOT(rlc_pP->is_data_plane),
|
||||
MBMS_FLAG_NO,
|
||||
rlc_pP->rb_id,
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
#if !ENABLE_ITTI
|
||||
RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
|
||||
#endif
|
||||
#endif
|
||||
rlc_pP->output_sdu_in_construction = NULL;
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND_SDU] ERROR SIZE <= 0 ... DO NOTHING, SET SDU SIZE TO 0\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//msg("[RLC_AM][MOD %d] Freeing mem_block ...\n", rlc_pP->module_id);
|
||||
//free_mem_block (rlc_pP->output_sdu_in_construction, __func__);
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.764
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
/*
|
||||
AssertFatal(3==4,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" SEND SDU REQUESTED %d bytes",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
*/
|
||||
}
|
||||
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_reassemble_pdu(const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
mem_block_t *const tb_pP,
|
||||
bool free_rlc_pdu) {
|
||||
int i,j;
|
||||
rlc_am_pdu_info_t *pdu_info = &((rlc_am_rx_pdu_management_t *)(tb_pP->data))->pdu_info;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU SN=%03d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info->sn);
|
||||
|
||||
if ( LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
rlc_am_display_data_pdu_infos(ctxt_pP, rlc_pP, pdu_info);
|
||||
}
|
||||
|
||||
if (pdu_info->e == RLC_E_FIXED_PART_DATA_FIELD_FOLLOW) {
|
||||
switch (pdu_info->fi) {
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=11 (00)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one complete SDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=10 (01)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one beginning segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP); // may be not necessary
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP,pdu_info->payload, pdu_info->payload_size);
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=01 (10)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
// one last segment of SDU
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
//} // else { clear sdu already done
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU NO E_LI FI=00 (11)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//if (rlc_pP->reassembly_missing_sn_detected == 0) {
|
||||
// one whole segment of SDU in PDU
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, pdu_info->payload, pdu_info->payload_size);
|
||||
//} else {
|
||||
// rlc_pP->reassembly_missing_sn_detected = 1; // not necessary but for readability of the code
|
||||
//}
|
||||
break;
|
||||
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1428
|
||||
LOG_E(RLC, "RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(0 != 0);
|
||||
}
|
||||
} else {
|
||||
switch (pdu_info->fi) {
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=11 (00) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=10 (01) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// N complete SDUs + one segment of SDU in PDU
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=01 (10) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
// one last segment of SDU + N complete SDUs in PDU
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
case RLC_FI_1ST_BYTE_DATA_IS_NOT_1ST_BYTE_SDU_LAST_BYTE_DATA_IS_NOT_LAST_BYTE_SDU:
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU FI=00 (11) Li=",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
for (i=0; i < pdu_info->num_li; i++) {
|
||||
LOG_D(RLC, "%d ",pdu_info->li_list[i]);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
//msg(" remaining size %d\n",size);
|
||||
j = 0;
|
||||
|
||||
for (i = 0; i < pdu_info->num_li; i++) {
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->li_list[i]);
|
||||
rlc_am_send_sdu(ctxt_pP, rlc_pP);
|
||||
j = j + pdu_info->li_list[i];
|
||||
}
|
||||
|
||||
if (pdu_info->hidden_size > 0) { // normally should always be > 0 but just for help debug
|
||||
// data is already ok, done by last loop above
|
||||
rlc_am_reassembly (ctxt_pP, rlc_pP, &pdu_info->payload[j], pdu_info->hidden_size);
|
||||
}
|
||||
|
||||
//rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.1429
|
||||
LOG_E(RLC, "not RLC_E_FIXED_PART_DATA_FIELD_FOLLOW error pdu_info->fi[%d]\n", pdu_info->fi);
|
||||
// assert(1 != 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (free_rlc_pdu) {
|
||||
free_mem_block(tb_pP, __func__);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_reassembly.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the reassembly of segments.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_reassembly_impl_ RLC AM Reassembly Internal Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_REASSEMBLY_H__
|
||||
# define __RLC_AM_REASSEMBLY_H__
|
||||
/*! \fn void rlc_am_clear_rx_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP)
|
||||
* \brief Reset the data cursor index in the output SDU buffer to zero.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_clear_rx_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_reassembly (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pPuint8_t * srcP, int32_t lengthP)
|
||||
* \brief Concatenate datas at the tail of the output SDU in construction. This SDU in construction will be sent to higher layer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] srcP Pointer on data to be reassemblied.
|
||||
* \param[in] lengthP Length of data to be reassemblied.
|
||||
*/
|
||||
void rlc_am_reassembly (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, uint8_t * srcP, int32_t lengthP);
|
||||
|
||||
/*! \fn void rlc_am_send_sdu (rlc_am_entity_t *rlc_pP,frame_t frameP)
|
||||
* \brief Send the output SDU in construction to higher layer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const mem_block_t* const tb_pP, bool free_rlc_pdu)
|
||||
* \brief Reassembly a RLC AM PDU, depending of the content of this PDU, data will be reassemblied to the current output SDU, the current will be sent to higher layers or not, after or before the reassembly, or no send of SDU will be triggered, depending on FI field in PDU header.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tb_pP RLC AM PDU embedded in a mem_block_t.
|
||||
* \param[in] free_rlc_pdu Flag for freeing RLC AM PDU after reassembly.
|
||||
*/
|
||||
void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, mem_block_t* const tb_pP, bool free_rlc_pdu);
|
||||
/** @} */
|
||||
#endif
|
||||
|
||||
@@ -1,533 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_RECEIVER_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "assertions.h"
|
||||
#include "rlc.h"
|
||||
#include "rlc_am.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_get_data_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t* header_pP,
|
||||
int16_t total_sizeP,
|
||||
rlc_am_pdu_info_t* pdu_info_pP)
|
||||
{
|
||||
memset(pdu_info_pP, 0, sizeof (rlc_am_pdu_info_t));
|
||||
|
||||
int16_t sum_li = 0;
|
||||
pdu_info_pP->d_c = header_pP->b1 >> 7;
|
||||
pdu_info_pP->num_li = 0;
|
||||
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.766
|
||||
if(pdu_info_pP->d_c == 0)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
|
||||
return -2;
|
||||
}
|
||||
/*
|
||||
AssertFatal (pdu_info_pP->d_c != 0, "RLC AM Rx PDU Data D/C Header Error LcId=%d\n", rlc_pP->channel_id);
|
||||
*/
|
||||
pdu_info_pP->rf = (header_pP->b1 >> 6) & 0x01;
|
||||
pdu_info_pP->p = (header_pP->b1 >> 5) & 0x01;
|
||||
pdu_info_pP->fi = (header_pP->b1 >> 3) & 0x03;
|
||||
pdu_info_pP->e = (header_pP->b1 >> 2) & 0x01;
|
||||
pdu_info_pP->sn = header_pP->b2 + (((uint16_t)(header_pP->b1 & 0x03)) << 8);
|
||||
|
||||
pdu_info_pP->header_size = 2;
|
||||
|
||||
if (pdu_info_pP->rf) {
|
||||
pdu_info_pP->lsf = (header_pP->data[0] >> 7) & 0x01;
|
||||
pdu_info_pP->so = header_pP->data[1] + (((uint16_t)(header_pP->data[0] & 0x7F)) << 8);
|
||||
pdu_info_pP->payload = &header_pP->data[2];
|
||||
pdu_info_pP->header_size += 2;
|
||||
} else {
|
||||
pdu_info_pP->payload = &header_pP->data[0];
|
||||
}
|
||||
|
||||
if (pdu_info_pP->e) {
|
||||
rlc_am_e_li_t *e_li;
|
||||
unsigned int li_length_in_bytes = 1;
|
||||
unsigned int li_to_read = 1;
|
||||
|
||||
if (pdu_info_pP->rf) {
|
||||
e_li = (rlc_am_e_li_t*)(&header_pP->data[2]);
|
||||
} else {
|
||||
e_li = (rlc_am_e_li_t*)(header_pP->data);
|
||||
}
|
||||
|
||||
while (li_to_read) {
|
||||
li_length_in_bytes = li_length_in_bytes ^ 3;
|
||||
|
||||
if (li_length_in_bytes == 2) {
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b1 << 4)) & 0x07F0;
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] |= (((uint8_t)(e_li->b2 >> 4)) & 0x000F);
|
||||
li_to_read = e_li->b1 & 0x80;
|
||||
pdu_info_pP->header_size += 2;
|
||||
} else {
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] = ((uint16_t)(e_li->b2 << 8)) & 0x0700;
|
||||
pdu_info_pP->li_list[pdu_info_pP->num_li] |= e_li->b3;
|
||||
li_to_read = e_li->b2 & 0x08;
|
||||
e_li++;
|
||||
pdu_info_pP->header_size += 1;
|
||||
}
|
||||
|
||||
sum_li += pdu_info_pP->li_list[pdu_info_pP->num_li];
|
||||
pdu_info_pP->num_li = pdu_info_pP->num_li + 1;
|
||||
|
||||
if (pdu_info_pP->num_li > RLC_AM_MAX_SDU_IN_PDU) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[GET PDU INFO] SN %04d TOO MANY LIs ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
if (li_length_in_bytes == 2) {
|
||||
pdu_info_pP->payload = &e_li->b3;
|
||||
} else {
|
||||
pdu_info_pP->payload = &e_li->b1;
|
||||
}
|
||||
}
|
||||
|
||||
pdu_info_pP->payload_size = total_sizeP - pdu_info_pP->header_size;
|
||||
|
||||
if (pdu_info_pP->payload_size > sum_li) {
|
||||
pdu_info_pP->hidden_size = pdu_info_pP->payload_size - sum_li;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_display_data_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
rlc_am_pdu_info_t* pdu_info_pP)
|
||||
{
|
||||
int num_li;
|
||||
|
||||
if (pdu_info_pP->d_c) {
|
||||
if (pdu_info_pP->rf) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d SO %05d LSF %01d POLL %1d ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn,
|
||||
pdu_info_pP->fi,
|
||||
pdu_info_pP->so,
|
||||
pdu_info_pP->lsf, pdu_info_pP->p);
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] RX DATA PDU SN %04d FI %1d POLL %1d ",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_pP->sn,
|
||||
pdu_info_pP->fi,
|
||||
pdu_info_pP->p);
|
||||
}
|
||||
|
||||
for (num_li = 0; num_li < pdu_info_pP->num_li; num_li++) {
|
||||
LOG_D(RLC, "LI %05d ", pdu_info_pP->li_list[num_li]);
|
||||
}
|
||||
|
||||
if (pdu_info_pP->hidden_size > 0) {
|
||||
LOG_D(RLC, "hidden size %05d ", pdu_info_pP->hidden_size);
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[DISPLAY DATA PDU] ERROR RX CONTROL PDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
}
|
||||
// assumed the sn of the tb_p is equal to VR(MS)
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_rx_update_vr_ms(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP)
|
||||
{
|
||||
//rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
|
||||
rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
|
||||
mem_block_t* cursor_p;
|
||||
|
||||
cursor_p = tb_pP;
|
||||
|
||||
if (cursor_p) {
|
||||
do {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
|
||||
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
|
||||
(rlc_pP->vr_ms != pdu_info_cursor_p->sn)) {
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(MS)] UPDATED VR(MS) %04d -> %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_ms, pdu_info_cursor_p->sn);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rlc_pP->vr_ms = RLC_AM_NEXT_SN(pdu_info_cursor_p->sn);
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (rlc_pP->vr_ms != rlc_pP->vr_h));
|
||||
|
||||
}
|
||||
}
|
||||
// assumed the sn of the tb_p is equal to VR(R)
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_rx_update_vr_r(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP)
|
||||
{
|
||||
rlc_am_pdu_info_t* pdu_info_cursor_p = NULL;
|
||||
mem_block_t* cursor_p;
|
||||
|
||||
cursor_p = tb_pP;
|
||||
|
||||
if (cursor_p) {
|
||||
do {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info;
|
||||
|
||||
if ((((rlc_am_rx_pdu_management_t*)(cursor_p->data))->all_segments_received == 0) ||
|
||||
(rlc_pP->vr_r != pdu_info_cursor_p->sn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[UPDATE VR(R)] UPDATED VR(R) %04d -> %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_r,
|
||||
(pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK);
|
||||
#endif
|
||||
|
||||
if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.rf == 1) {
|
||||
if (((rlc_am_rx_pdu_management_t*)(cursor_p->data))->pdu_info.lsf == 1) {
|
||||
rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
} else {
|
||||
rlc_pP->vr_r = (rlc_pP->vr_r + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
|
||||
cursor_p = cursor_p->next;
|
||||
} while (cursor_p != NULL);
|
||||
|
||||
//rlc_pP->vr_r = (pdu_info_cursor_p->sn + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_routing (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
struct mac_data_ind data_indP)
|
||||
{
|
||||
mem_block_t *tb_p = NULL;
|
||||
uint8_t *first_byte_p = NULL;
|
||||
sdu_size_t tb_size_in_bytes;
|
||||
RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
|
||||
|
||||
while ((tb_p = list_remove_head (&data_indP.data))) {
|
||||
first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
|
||||
tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
|
||||
|
||||
if (tb_size_in_bytes > 0) {
|
||||
if ((*first_byte_p & 0x80) == 0x80) {
|
||||
rlc_pP->stat_rx_data_bytes += tb_size_in_bytes;
|
||||
rlc_pP->stat_rx_data_pdu += 1;
|
||||
rlc_am_receive_process_data_pdu (ctxt_pP, rlc_pP, tb_p, first_byte_p, tb_size_in_bytes);
|
||||
} else {
|
||||
rlc_pP->stat_rx_control_bytes += tb_size_in_bytes;
|
||||
rlc_pP->stat_rx_control_pdu += 1;
|
||||
rlc_am_receive_process_control_pdu (ctxt_pP, rlc_pP, tb_p, &first_byte_p, &tb_size_in_bytes);
|
||||
// Test if remaining bytes not processed (up to know, highest probability is bug in MAC)
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.767
|
||||
if(tb_size_in_bytes != 0)
|
||||
{
|
||||
LOG_E(RLC, "Remaining %d bytes following a control PDU\n",
|
||||
tb_size_in_bytes);
|
||||
}
|
||||
/*
|
||||
AssertFatal( tb_size_in_bytes == 0,
|
||||
"Remaining %d bytes following a control PDU",
|
||||
tb_size_in_bytes);
|
||||
*/
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RX ROUTING] VR(R)=%03d VR(MR)=%03d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_mr);
|
||||
}
|
||||
} // end while
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_process_data_pdu (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
mem_block_t* tb_pP,
|
||||
uint8_t* first_byte_pP,
|
||||
uint16_t tb_size_in_bytesP)
|
||||
{
|
||||
// 5.1.3.2 Receive operations
|
||||
// 5.1.3.2.1 General
|
||||
// The receiving side of an AM RLC entity shall maintain a receiving window according to state variables VR(R) and
|
||||
// VR(MR) as follows:
|
||||
// - a SN falls within the receiving window if VR(R) <= SN < VR(MR);
|
||||
// - a SN falls outside of the receiving window otherwise.
|
||||
//
|
||||
// When receiving a RLC data PDU from lower layer, the receiving side of an AM RLC entity shall:
|
||||
// - either discard the received RLC data PDU or place it in the reception buffer (see sub clause 5.1.3.2.2);
|
||||
// - if the received RLC data PDU was placed in the reception buffer:
|
||||
// - update state variables, reassemble and deliver RLC SDUs to upper layer and start/stop t-Reordering as
|
||||
// needed (see sub clause 5.1.3.2.3).
|
||||
// When t-Reordering expires, the receiving side of an AM RLC entity shall:
|
||||
// - update state variables and start t-Reordering as needed (see sub clause 5.1.3.2.4).
|
||||
|
||||
|
||||
// 5.1.3.2.2 Actions when a RLC data PDU is received from lower layer
|
||||
// When a RLC data PDU is received from lower layer, where the RLC data PDU contains byte segment numbers y to z of
|
||||
// an AMD PDU with SN = x, the receiving side of an AM RLC entity shall:
|
||||
// - if x falls outside of the receiving window; or
|
||||
// - if byte segment numbers y to z of the AMD PDU with SN = x have been received before:
|
||||
// - discard the received RLC data PDU;
|
||||
// - else:
|
||||
// - place the received RLC data PDU in the reception buffer;
|
||||
// - if some byte segments of the AMD PDU contained in the RLC data PDU have been received before:
|
||||
// - discard the duplicate byte segments.
|
||||
rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info;
|
||||
rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP;
|
||||
rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK;
|
||||
bool reassemble = false;
|
||||
|
||||
if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) {
|
||||
|
||||
((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received = 0;
|
||||
|
||||
if (RLC_AM_SN_IN_WINDOW(pdu_info_p->sn, rlc_pP->vr_r)) {
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] VR(R) %04d VR(H) %04d VR(MR) %04d VR(MS) %04d VR(X) %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_p->sn,
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_h,
|
||||
rlc_pP->vr_mr,
|
||||
rlc_pP->vr_ms,
|
||||
rlc_pP->vr_x);
|
||||
|
||||
pdu_status = rlc_am_rx_list_check_duplicate_insert_pdu(ctxt_pP, rlc_pP,tb_pP);
|
||||
if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
|
||||
rlc_pP->stat_rx_data_pdu_dropped += 1;
|
||||
rlc_pP->stat_rx_data_bytes_dropped += tb_size_in_bytesP;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED CAUSE=%d SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_status,pdu_info_p->sn);
|
||||
#if RLC_STOP_ON_LOST_PDU
|
||||
AssertFatal( 0 == 1,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT" LOST PDU DETECTED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
} else {
|
||||
// 5.1.3.2.3
|
||||
// Actions when a RLC data PDU is placed in the reception buffer
|
||||
//
|
||||
// When a RLC data PDU with SN = x is placed in the reception buffer, the receiving side of an AM RLC entity shall:
|
||||
// - if x >= VR(H)
|
||||
// - update VR(H) to x+ 1;
|
||||
//
|
||||
// - if all byte segments of the AMD PDU with SN = VR(MS) are received:
|
||||
// - update VR(MS) to the SN of the first AMD PDU with SN > current VR(MS) for which not all byte segments
|
||||
// have been received;
|
||||
//
|
||||
// - if x = VR(R):
|
||||
// - if all byte segments of the AMD PDU with SN = VR(R) are received:
|
||||
// - update VR(R) to the SN of the first AMD PDU with SN > current VR(R) for which not all byte segments
|
||||
// have been received;
|
||||
// - update VR(MR) to the updated VR(R) + AM_Window_Size;
|
||||
//
|
||||
// - reassemble RLC SDUs from any byte segments of AMD PDUs with SN that falls outside of the receiving
|
||||
// window and in-sequence byte segments of the AMD PDU with SN = VR(R), remove RLC headers when
|
||||
// doing so and deliver the reassembled RLC SDUs to upper layer in sequence if not delivered before;
|
||||
//
|
||||
// - if t-Reordering is running:
|
||||
// - if VR(X) = VR(R); or
|
||||
// - if VR(X) falls outside of the receiving window and VR(X) is not equal to VR(MR):
|
||||
// - stop and reset t-Reordering;
|
||||
//
|
||||
// - if t-Reordering is not running (includes the case t-Reordering is stopped due to actions above):
|
||||
// - if VR (H) > VR(R):
|
||||
// - start t-Reordering;
|
||||
// - set VR(X) to VR(H).
|
||||
|
||||
|
||||
#if TRACE_RLC_AM_RX
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] RX LIST AFTER INSERTION:\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_am_rx_list_display(rlc_pP, "rlc_am_receive_process_data_pdu AFTER INSERTION ");
|
||||
#endif
|
||||
|
||||
/* 1) Update vrH if sn >= vrH */
|
||||
if (RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) >= RLC_AM_DIFF_SN(rlc_pP->vr_h,rlc_pP->vr_r))
|
||||
{
|
||||
rlc_pP->vr_h = RLC_AM_NEXT_SN(pdu_info_p->sn);
|
||||
}
|
||||
|
||||
rlc_am_rx_check_all_byte_segments(ctxt_pP, rlc_pP, tb_pP);
|
||||
|
||||
/* 2) Reordering Window Processing: Update vr_ms if sn = vr_ms and all bytes received for sn */
|
||||
if ((pdu_info_p->sn == rlc_pP->vr_ms) && (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received)) {
|
||||
rlc_am_rx_update_vr_ms(ctxt_pP, rlc_pP, tb_pP);
|
||||
}
|
||||
|
||||
if (pdu_info_p->sn == rlc_pP->vr_r) {
|
||||
mem_block_t* cursor_p = rlc_pP->receiver_buffer.head;
|
||||
rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data);
|
||||
if( (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) == (pdu_cursor_mgnt_p->all_segments_received)){
|
||||
if (((rlc_am_rx_pdu_management_t*)(tb_pP->data))->all_segments_received) {
|
||||
rlc_am_rx_update_vr_r(ctxt_pP, rlc_pP, tb_pP);
|
||||
rlc_pP->vr_mr = (rlc_pP->vr_r + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
|
||||
}
|
||||
reassemble = rlc_am_rx_check_vr_reassemble(ctxt_pP, rlc_pP);
|
||||
//TODO : optimization : check whether a reassembly is needed by looking at LI, FI, SO, etc...
|
||||
}else{
|
||||
LOG_E(RLC, "BAD all_segments_received!!! discard buffer!!!\n");
|
||||
/* Discard received block if out of window, duplicate or header error */
|
||||
free_mem_block (tb_pP, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
//FNA: fix check VrX out of receiving window
|
||||
if ((rlc_pP->t_reordering.running) || ((rlc_pP->t_reordering.ms_duration == 0) && (rlc_pP->vr_x != RLC_SN_UNDEFINED))) {
|
||||
if ((rlc_pP->vr_x == rlc_pP->vr_r) || (!(RLC_AM_SN_IN_WINDOW(rlc_pP->vr_x, rlc_pP->vr_r)) && (rlc_pP->vr_x != rlc_pP->vr_mr))) {
|
||||
rlc_am_stop_and_reset_timer_reordering(ctxt_pP, rlc_pP);
|
||||
rlc_pP->vr_x = RLC_SN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(rlc_pP->t_reordering.running)) {
|
||||
if (rlc_pP->vr_h != rlc_pP->vr_r) { // - if VR (H) > VR(R) translated to - if VR (H) != VR(R)
|
||||
rlc_pP->vr_x = rlc_pP->vr_h;
|
||||
if (rlc_pP->t_reordering.ms_duration != 0) {
|
||||
rlc_am_start_timer_reordering(ctxt_pP, rlc_pP);
|
||||
}
|
||||
else {
|
||||
/* specific case for no timer reordering configured */
|
||||
/* reordering window directly advances with vrH */
|
||||
rlc_pP->vr_ms = rlc_pP->vr_h;
|
||||
|
||||
/* Trigger a Status and clear any existing Delay Flag */
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU SN=%04d] NEW VR(R) %04d VR(H) %04d VR(MS) %04d VR(MR) %04d VR(X) %04d reassemble=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_info_p->sn,
|
||||
rlc_pP->vr_r,
|
||||
rlc_pP->vr_h,
|
||||
rlc_pP->vr_ms,
|
||||
rlc_pP->vr_mr,
|
||||
rlc_pP->vr_x,
|
||||
reassemble);
|
||||
} else {
|
||||
rlc_pP->stat_rx_data_pdu_out_of_window += 1;
|
||||
rlc_pP->stat_rx_data_bytes_out_of_window += tb_size_in_bytesP;
|
||||
pdu_status = RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU OUT OF RX WINDOW, DISCARDED, SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
|
||||
}
|
||||
|
||||
/* 3) Check for triggering a Tx Status PDU if a poll is received or if a pending status was delayed */
|
||||
if ((pdu_info_p->p) && (pdu_status < RLC_AM_DATA_PDU_STATUS_BUFFER_FULL)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] POLL BIT SET, STATUS REQUESTED:\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
/* Polling Info Saving for In and Out of Window PDU */
|
||||
/* avoid multi status trigger */
|
||||
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) ||
|
||||
!(RLC_AM_GET_STATUS(rlc_pP->status_requested,(RLC_AM_STATUS_TRIGGERED_POLL | RLC_AM_STATUS_TRIGGERED_T_REORDERING))))
|
||||
{
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_POLL);
|
||||
|
||||
if ((pdu_status != RLC_AM_DATA_PDU_STATUS_OK) || ((pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
|
||||
(!(RLC_AM_SN_IN_WINDOW(pdu_info_p->sn,rlc_pP->vr_r)) ||
|
||||
(RLC_AM_DIFF_SN(pdu_info_p->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
|
||||
)
|
||||
)
|
||||
{
|
||||
/* Conditions are met for sending a Status Report */
|
||||
/* Then clear Delay Flag and reset its corresponding sn */
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
else if (rlc_pP->sn_status_triggered_delayed == RLC_SN_UNDEFINED)
|
||||
{
|
||||
/* Delay status trigger if pdustatus OK and sn>= vr_ms */
|
||||
/* Note: vr_r and vr_ms have been updated */
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = pdu_info_p->sn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ReEnable a previously delayed Status Trigger if PDU discarded or */
|
||||
/* sn no more in RxWindow due to RxWindow advance or sn < vr_ms */
|
||||
if ((RLC_AM_GET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED)) &&
|
||||
(pdu_status == RLC_AM_DATA_PDU_STATUS_OK) &&
|
||||
(!(RLC_AM_SN_IN_WINDOW(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r)) ||
|
||||
(RLC_AM_DIFF_SN(rlc_pP->sn_status_triggered_delayed,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)))
|
||||
)
|
||||
{
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
pdu_status = RLC_AM_DATA_PDU_STATUS_HEADER_ERROR;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[PROCESS RX PDU] PDU DISCARDED BAD HEADER FORMAT SN=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_info_p->sn);
|
||||
}
|
||||
|
||||
if (pdu_status != RLC_AM_DATA_PDU_STATUS_OK) {
|
||||
/* Discard received block if out of window, duplicate or header error */
|
||||
free_mem_block (tb_pP, __func__);
|
||||
}
|
||||
else if (reassemble) {
|
||||
/* Reassemble SDUs */
|
||||
rlc_am_rx_list_reassemble_rlc_sdus(ctxt_pP, rlc_pP);
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_receiver.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the first stage of the receiving process.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_receiver_impl_ RLC AM Receiver Internal Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_AM_RECEIVER_H__
|
||||
# define __RLC_AM_RECEIVER_H__
|
||||
/*! \fn signed int rlc_am_get_data_pdu_infos( const protocol_ctxt_t* const ctxt_pP, const rlc_am_entity_t * const rlc_pP,rlc_am_pdu_sn_10_t* headerP, int16_t sizeP, rlc_am_pdu_info_t* pdu_infoP)
|
||||
* \brief Extract PDU informations (header fields, data size, etc) from the serialized PDU.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] headerP RLC AM header PDU pointer.
|
||||
* \param[in] sizeP Size of RLC AM PDU.
|
||||
* \param[in] pdu_infoP Structure containing extracted informations from PDU.
|
||||
* \return 0 if no error was encountered during the parsing of the PDU, else -1;
|
||||
*/
|
||||
signed int rlc_am_get_data_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t * const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t* headerP,
|
||||
int16_t sizeP,
|
||||
rlc_am_pdu_info_t* pdu_infoP);
|
||||
|
||||
/*! \fn void rlc_am_display_data_pdu_infos(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, rlc_am_pdu_info_t* pdu_infoP)
|
||||
* \brief Display RLC AM PDU informations.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] pdu_infoP Structure containing extracted informations of a PDU.
|
||||
*/
|
||||
void rlc_am_display_data_pdu_infos(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t * const rlc_pP, rlc_am_pdu_info_t* pdu_infoP);
|
||||
|
||||
/*! \fn void rlc_am_rx_update_vr_ms(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t * const rlc_pP,mem_block_t* tb_pP)
|
||||
* \brief Update RLC AM protocol variable VR(MS).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tb_pP PDU embedded in a mem_block_t struct.
|
||||
* \note It is assumed that the sequence number of the transport block is equal to VR(MS)
|
||||
*/
|
||||
void rlc_am_rx_update_vr_ms(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, mem_block_t* tb_pP);
|
||||
|
||||
/*! \fn void rlc_am_rx_update_vr_r (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP,mem_block_t* tb_pP)
|
||||
* \brief Update RLC AM protocol variable VR(R).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tb_pP PDU embedded in a mem_block_t struct.
|
||||
* \note It is assumed that the sequence number of the transport block is equal to VR(R)
|
||||
*/
|
||||
void rlc_am_rx_update_vr_r (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, mem_block_t* tb_pP);
|
||||
|
||||
/*! \fn void rlc_am_receive_routing (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, struct mac_data_ind data_indP)
|
||||
* \brief Convert transport blocks received from MAC layer into RLC AM PDUs, and dispatch to the right processing block these PDUS upon their type (CONTROL/DATA).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] data_indP Transport blocks received from MAC layer.
|
||||
*/
|
||||
void rlc_am_receive_routing (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, struct mac_data_ind data_indP);
|
||||
|
||||
/*! \fn void rlc_am_receive_process_data_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, mem_block_t* tb_pP, uint8_t* first_byteP, uint16_t tb_size_in_bytesP)
|
||||
* \brief Process an incoming data PDU received from MAC layer.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tb_pP PDU embedded in a mem_block_t struct.
|
||||
* \param[in] first_byteP Pointer on first byte of the PDU.
|
||||
* \param[in] tb_size_in_bytesP Transport block size in bytes (same as PDU size in bytes).
|
||||
*/
|
||||
void rlc_am_receive_process_data_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlc_pP, mem_block_t* tb_pP, uint8_t* first_byteP,
|
||||
uint16_t tb_size_in_bytesP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,977 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_RETRANSMIT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
//#include "rtos_header.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "rlc.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
bool rlc_am_nack_pdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const rlc_sn_t snP,
|
||||
const rlc_sn_t prev_nack_snP,
|
||||
sdu_size_t so_startP,
|
||||
sdu_size_t so_endP)
|
||||
{
|
||||
// 5.2.1 Retransmission
|
||||
// ...
|
||||
// When an AMD PDU or a portion of an AMD PDU is considered for retransmission, the transmitting side of the AM
|
||||
// RLC entity shall:
|
||||
// - if the AMD PDU is considered for retransmission for the first time:
|
||||
// - set the RETX_COUNT associated with the AMD PDU to zero;
|
||||
// - else, if it (the AMD PDU or the portion of the AMD PDU that is considered for retransmission) is not pending
|
||||
// for retransmission already, or a portion of it is not pending for retransmission already:
|
||||
// - increment the RETX_COUNT;
|
||||
// - if RETX_COUNT = maxRetxThreshold:
|
||||
// - indicate to upper layers that max retransmission has been reached.
|
||||
|
||||
|
||||
mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block;
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE];
|
||||
//int pdu_sdu_index;
|
||||
//int sdu_index;
|
||||
bool status = true;
|
||||
bool retx_count_increment = false;
|
||||
sdu_size_t pdu_data_to_retx = 0;
|
||||
|
||||
if (mb_p != NULL) {
|
||||
//assert(so_startP <= so_endP);
|
||||
if(so_startP > so_endP) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU, so_startP %d, so_endP %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),so_startP, so_endP);
|
||||
status = false;
|
||||
}
|
||||
// Handle full PDU NACK first
|
||||
else if ((so_startP == 0) && (so_endP == 0x7FFF)) {
|
||||
if ((prev_nack_snP != snP) && (tx_data_pdu_buffer_p->flags.ack == 0) && (tx_data_pdu_buffer_p->flags.max_retransmit == 0)) {
|
||||
pdu_data_to_retx = tx_data_pdu_buffer_p->payload_size;
|
||||
/* Increment VtReTxNext if this is the first NACK or if some segments have already been transmitted */
|
||||
if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (tx_data_pdu_buffer_p->nack_so_start))
|
||||
retx_count_increment = true;
|
||||
|
||||
tx_data_pdu_buffer_p->nack_so_start = 0;
|
||||
tx_data_pdu_buffer_p->num_holes = 0;
|
||||
tx_data_pdu_buffer_p->retx_hole_index = 0;
|
||||
tx_data_pdu_buffer_p->nack_so_stop = tx_data_pdu_buffer_p->payload_size - 1;
|
||||
#if TRACE_RLC_AM_HOLE
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[HOLE] SN %04d GLOBAL NACK 0->%05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
snP,
|
||||
so_stopP);
|
||||
#endif
|
||||
//assert(tx_data_pdu_buffer_p->nack_so_start < tx_data_pdu_buffer_p->payload_size);
|
||||
if(tx_data_pdu_buffer_p->nack_so_start >= tx_data_pdu_buffer_p->payload_size){
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU, nack_so_start %d, payload_size %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),tx_data_pdu_buffer_p->nack_so_start, tx_data_pdu_buffer_p->payload_size);
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
else if (tx_data_pdu_buffer_p->flags.max_retransmit == 0) {
|
||||
// Handle Segment offset
|
||||
if (so_endP == 0x7FFF) {
|
||||
so_endP = tx_data_pdu_buffer_p->payload_size - 1;
|
||||
}
|
||||
|
||||
// Check consistency
|
||||
if ((so_startP <= so_endP) && (so_endP < tx_data_pdu_buffer_p->payload_size)) {
|
||||
if (prev_nack_snP != snP) {
|
||||
/* New NACK_SN with SO */
|
||||
/* check whether a new segment is to be placed in Retransmission Buffer, then increment vrReTx */
|
||||
if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (so_startP < tx_data_pdu_buffer_p->nack_so_start))
|
||||
retx_count_increment = true;
|
||||
|
||||
tx_data_pdu_buffer_p->num_holes = 1;
|
||||
tx_data_pdu_buffer_p->retx_hole_index = 0;
|
||||
tx_data_pdu_buffer_p->hole_so_start[0] = so_startP;
|
||||
tx_data_pdu_buffer_p->hole_so_stop[0] = so_endP;
|
||||
tx_data_pdu_buffer_p->nack_so_start = so_startP;
|
||||
tx_data_pdu_buffer_p->nack_so_stop = so_endP;
|
||||
pdu_data_to_retx = so_endP - so_startP + 1;
|
||||
|
||||
}
|
||||
else if ((tx_data_pdu_buffer_p->num_holes) && (tx_data_pdu_buffer_p->num_holes < RLC_AM_MAX_HOLES_REPORT_PER_PDU)) {
|
||||
/* New SOStart/SOEnd for the same NACK_SN than before */
|
||||
/* check discontinuity */
|
||||
if (so_startP > tx_data_pdu_buffer_p->hole_so_stop[tx_data_pdu_buffer_p->num_holes - 1]) {
|
||||
tx_data_pdu_buffer_p->hole_so_start[tx_data_pdu_buffer_p->num_holes] = so_startP;
|
||||
tx_data_pdu_buffer_p->hole_so_stop[tx_data_pdu_buffer_p->num_holes] = so_endP;
|
||||
tx_data_pdu_buffer_p->nack_so_stop = so_endP;
|
||||
tx_data_pdu_buffer_p->num_holes ++;
|
||||
pdu_data_to_retx = so_endP - so_startP + 1;
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
tx_data_pdu_buffer_p->flags.nack = 1;
|
||||
if ((retx_count_increment) && (tx_data_pdu_buffer_p->retx_count == tx_data_pdu_buffer_p->retx_count_next)) {
|
||||
tx_data_pdu_buffer_p->retx_count_next ++;
|
||||
}
|
||||
if (tx_data_pdu_buffer_p->flags.retransmit == 1) {
|
||||
if (prev_nack_snP != snP) {
|
||||
/* if first process of this NACK_SN and data already pending for retx */
|
||||
rlc_pP->retrans_num_bytes_to_retransmit += (pdu_data_to_retx - tx_data_pdu_buffer_p->retx_payload_size);
|
||||
tx_data_pdu_buffer_p->retx_payload_size = pdu_data_to_retx;
|
||||
}
|
||||
else if (tx_data_pdu_buffer_p->num_holes > 1) {
|
||||
/* Segment case : SOStart and SOEnd already received for same NACK_SN */
|
||||
/* filter case where a NACK_SN is received twice with SO first time and no SO second time */
|
||||
rlc_pP->retrans_num_bytes_to_retransmit += pdu_data_to_retx;
|
||||
tx_data_pdu_buffer_p->retx_payload_size += pdu_data_to_retx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
tx_data_pdu_buffer_p->flags.retransmit = 1;
|
||||
rlc_pP->retrans_num_bytes_to_retransmit += pdu_data_to_retx;
|
||||
tx_data_pdu_buffer_p->retx_payload_size = pdu_data_to_retx;
|
||||
rlc_pP->retrans_num_pdus ++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU SN %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
snP);
|
||||
status = false;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_ack_pdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const rlc_sn_t snP,
|
||||
bool free_pdu)
|
||||
{
|
||||
mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block;
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE];
|
||||
|
||||
tx_data_pdu_buffer->flags.retransmit = 0;
|
||||
|
||||
if (mb_p != NULL) {
|
||||
if (free_pdu) {
|
||||
free_mem_block(mb_p, __func__);
|
||||
tx_data_pdu_buffer->mem_block = NULL;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] ACK PDU SN %05d previous retx_count %d \n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
snP,
|
||||
tx_data_pdu_buffer->retx_count);
|
||||
}
|
||||
|
||||
if (tx_data_pdu_buffer->retx_payload_size) {
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.768
|
||||
if(tx_data_pdu_buffer->flags.ack != 0)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Rx Status Report sn=%d acked twice but is pending for Retx vtA=%d vtS=%d LcId=%d\n",
|
||||
snP, rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
AssertFatal (tx_data_pdu_buffer->flags.ack == 0,
|
||||
"RLC AM Rx Status Report sn=%d acked twice but is pending for Retx vtA=%d vtS=%d LcId=%d\n",
|
||||
snP, rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_buffer->retx_payload_size;
|
||||
tx_data_pdu_buffer->retx_payload_size = 0;
|
||||
tx_data_pdu_buffer->num_holes = 0;
|
||||
rlc_pP->retrans_num_pdus --;
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[ACK-PDU] WARNING ACK PDU SN %05d -> NO PDU TO ACK\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
snP);
|
||||
|
||||
if (mb_p != NULL) {
|
||||
free_mem_block(mb_p, __func__);
|
||||
tx_data_pdu_buffer->mem_block = NULL;
|
||||
}
|
||||
}
|
||||
tx_data_pdu_buffer->flags.ack = 1;
|
||||
tx_data_pdu_buffer->flags.transmitted = 0;
|
||||
tx_data_pdu_buffer->flags.retransmit = 0;
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
mem_block_t* rlc_am_retransmit_get_copy (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
mem_block_t* mb_original_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block;
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.784
|
||||
if(mb_original_p == NULL)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM PDU Copy Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
snP,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (mb_original_p != NULL, "RLC AM PDU Copy Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
snP,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
rlc_am_tx_data_pdu_management_t *pdu_mngt = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE];
|
||||
|
||||
/* We need to allocate a new buffer and copy to it because header content may change for Polling bit */
|
||||
int size = pdu_mngt->header_and_payload_size + sizeof(struct mac_tb_req);
|
||||
mem_block_t* mb_copy = get_free_mem_block(size, __func__);
|
||||
if(mb_copy == NULL) return NULL;
|
||||
memcpy(mb_copy->data, mb_original_p->data, size);
|
||||
|
||||
rlc_am_pdu_sn_10_t *pdu_p = (rlc_am_pdu_sn_10_t*) (&mb_copy->data[sizeof(struct mac_tb_req)]);
|
||||
((struct mac_tb_req*)(mb_copy->data))->data_ptr = (uint8_t*)pdu_p;
|
||||
|
||||
return mb_copy;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
mem_block_t* rlc_am_retransmit_get_am_segment(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
rlc_am_tx_data_pdu_management_t *const pdu_mngt,
|
||||
sdu_size_t * const payload_sizeP /* in-out*/)
|
||||
{
|
||||
int16_t sdus_segment_size[RLC_AM_MAX_SDU_IN_PDU];
|
||||
mem_block_t* mb_original_p = pdu_mngt->mem_block;
|
||||
mem_block_t* mem_pdu_segment_p = NULL;
|
||||
uint8_t *pdu_original_header_p = NULL;
|
||||
uint8_t *pdu_segment_header_p = NULL;
|
||||
sdu_size_t retx_so_start,retx_so_stop; //starting and ending SO for retransmission in this PDU
|
||||
rlc_sn_t sn = pdu_mngt->sn;
|
||||
uint16_t header_so_part;
|
||||
bool fi_start, fi_end;
|
||||
uint8_t sdu_index = 0;
|
||||
uint8_t sdu_segment_index = 0;
|
||||
uint8_t num_LIs_pdu_segment = pdu_mngt->nb_sdus - 1;
|
||||
uint8_t li_bit_offset = 4; /* toggle between 0 and 4 */
|
||||
uint8_t li_jump_offset = 1; /* toggle between 1 and 2 */
|
||||
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.774
|
||||
if(mb_original_p == NULL)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM PDU Segment Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (mb_original_p != NULL, "RLC AM PDU Segment Error: Empty block sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.775
|
||||
if(pdu_mngt->payload != mb_original_p->data + sizeof(struct mac_tb_req) + pdu_mngt->header_and_payload_size - pdu_mngt->payload_size)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM PDU Segment Error: Inconsistent data pointers p1=%p p2=%p sn = %d total size = %d data size = %d LcId=%d !\n",
|
||||
pdu_mngt->payload,mb_original_p->data + sizeof(struct mac_tb_req),pdu_mngt->header_and_payload_size,pdu_mngt->payload_size,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (pdu_mngt->payload == mb_original_p->data + sizeof(struct mac_tb_req) + pdu_mngt->header_and_payload_size - pdu_mngt->payload_size,
|
||||
"RLC AM PDU Segment Error: Inconsistent data pointers p1=%p p2=%p sn = %d total size = %d data size = %d LcId=%d !\n",
|
||||
pdu_mngt->payload,mb_original_p->data + sizeof(struct mac_tb_req),pdu_mngt->header_and_payload_size,pdu_mngt->payload_size,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
/* Init ReTx Hole list if not configured, ie the whole PDU has to be retransmitted */
|
||||
if (pdu_mngt->num_holes == 0)
|
||||
{
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.776
|
||||
if(pdu_mngt->retx_payload_size != pdu_mngt->payload_size)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM PDU ReTx Segment: Expecting full PDU size ReTxSize=%d DataSize=%d sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
pdu_mngt->retx_payload_size,pdu_mngt->payload_size,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (pdu_mngt->retx_payload_size == pdu_mngt->payload_size,"RLC AM PDU ReTx Segment: Expecting full PDU size ReTxSize=%d DataSize=%d sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
pdu_mngt->retx_payload_size,pdu_mngt->payload_size,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
pdu_mngt->retx_hole_index = 0;
|
||||
pdu_mngt->hole_so_start[0] = 0;
|
||||
pdu_mngt->hole_so_stop[0] = pdu_mngt->payload_size - 1;
|
||||
pdu_mngt->num_holes = 1;
|
||||
}
|
||||
|
||||
/* Init SO Start and SO Stop */
|
||||
retx_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index];
|
||||
retx_so_stop = pdu_mngt->hole_so_stop[pdu_mngt->retx_hole_index];
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.777
|
||||
if((retx_so_start > retx_so_stop) || (retx_so_stop - retx_so_start + 1 > pdu_mngt->payload_size))
|
||||
{
|
||||
LOG_E(RLC,"RLC AM Tx PDU Segment Data SO Error: retx_so_start=%d retx_so_stop=%d OriginalPDUDataLength=%d sn=%d LcId=%d!\n",
|
||||
retx_so_start,retx_so_stop,pdu_mngt->payload_size,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal ((retx_so_start <= retx_so_stop) && (retx_so_stop - retx_so_start + 1 <= pdu_mngt->payload_size),
|
||||
"RLC AM Tx PDU Segment Data SO Error: retx_so_start=%d retx_so_stop=%d OriginalPDUDataLength=%d sn=%d LcId=%d!\n",
|
||||
retx_so_start,retx_so_stop,pdu_mngt->payload_size,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
/* Init FI to the same value as original PDU */
|
||||
fi_start = (!(RLC_AM_PDU_GET_FI_START(*(pdu_mngt->first_byte))));
|
||||
fi_end = (!(RLC_AM_PDU_GET_FI_END(*(pdu_mngt->first_byte))));
|
||||
|
||||
/* Handle no LI case first */
|
||||
if (num_LIs_pdu_segment == 0)
|
||||
{
|
||||
/* Bound retx_so_stop to available TBS */
|
||||
if (retx_so_stop - retx_so_start + 1 + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE > rlc_pP->nb_bytes_requested_by_mac)
|
||||
{
|
||||
retx_so_stop = retx_so_start + rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE - 1;
|
||||
}
|
||||
|
||||
*payload_sizeP = retx_so_stop - retx_so_start + 1;
|
||||
|
||||
mem_pdu_segment_p = get_free_mem_block((*payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + sizeof(struct mac_tb_req)), __func__);
|
||||
if(mem_pdu_segment_p == NULL) return NULL;
|
||||
pdu_segment_header_p = (uint8_t *)&mem_pdu_segment_p->data[sizeof(struct mac_tb_req)];
|
||||
((struct mac_tb_req*)(mem_pdu_segment_p->data))->data_ptr = pdu_segment_header_p;
|
||||
((struct mac_tb_req*)(mem_pdu_segment_p->data))->tb_size = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE + *payload_sizeP;
|
||||
|
||||
/* clear all PDU segment */
|
||||
memset(pdu_segment_header_p, 0, *payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE);
|
||||
/* copy data part */
|
||||
memcpy(pdu_segment_header_p + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE, pdu_mngt->payload + retx_so_start, *payload_sizeP);
|
||||
|
||||
/* Set FI part to false if SO Start and SO End are different from PDU boundaries */
|
||||
if (retx_so_start)
|
||||
{
|
||||
fi_start = false;
|
||||
}
|
||||
if (retx_so_stop < pdu_mngt->payload_size - 1)
|
||||
{
|
||||
fi_end = false;
|
||||
}
|
||||
|
||||
/* Header content is filled at the end */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Step 1 */
|
||||
/* Find the SDU index in the original PDU containing retx_so_start */
|
||||
sdu_size_t sdu_size = 0;
|
||||
sdu_size_t data_size = 0;
|
||||
*payload_sizeP = 0;
|
||||
sdu_size_t header_segment_length = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE;
|
||||
pdu_original_header_p = pdu_mngt->first_byte + 2;
|
||||
li_bit_offset = 4; /* toggle between 0 and 4 */
|
||||
li_jump_offset = 1; /* toggle between 1 and 2 */
|
||||
uint16_t temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1));
|
||||
|
||||
|
||||
/* Read first LI */
|
||||
sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset);
|
||||
pdu_original_header_p += li_jump_offset;
|
||||
li_bit_offset ^= 0x4;
|
||||
li_jump_offset ^= 0x3;
|
||||
data_size += sdu_size;
|
||||
sdu_index = 1;
|
||||
|
||||
/* Loop on all original LIs */
|
||||
while ((data_size < retx_so_start + 1) && (sdu_index < pdu_mngt->nb_sdus))
|
||||
{
|
||||
if (sdu_index < pdu_mngt->nb_sdus - 1)
|
||||
{
|
||||
temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1));
|
||||
sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset);
|
||||
pdu_original_header_p += li_jump_offset;
|
||||
li_bit_offset ^= 0x4;
|
||||
li_jump_offset ^= 0x3;
|
||||
data_size += sdu_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if retx_so_start is still not included then set data_size with full original PDU data size */
|
||||
/* Set fi_start to false in this case */
|
||||
data_size = pdu_mngt->payload_size;
|
||||
}
|
||||
sdu_index ++;
|
||||
}
|
||||
|
||||
if (retx_so_start == data_size)
|
||||
{
|
||||
/* Set FI Start if retx_so_start = cumulated data size */
|
||||
fi_start = true;
|
||||
/* there must be at least one SDU more */
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.778
|
||||
if(sdu_index >= pdu_mngt->nb_sdus)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM Tx PDU Segment Error: sdu_index=%d nb_sdus=%d sn=%d LcId=%d !\n",
|
||||
sdu_index,pdu_mngt->nb_sdus,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (sdu_index < pdu_mngt->nb_sdus, "RLC AM Tx PDU Segment Error: sdu_index=%d nb_sdus=%d sn=%d LcId=%d !\n",
|
||||
sdu_index,pdu_mngt->nb_sdus,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
if (sdu_index < pdu_mngt->nb_sdus - 1)
|
||||
{
|
||||
temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1));
|
||||
sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset);
|
||||
pdu_original_header_p += li_jump_offset;
|
||||
li_bit_offset ^= 0x4;
|
||||
li_jump_offset ^= 0x3;
|
||||
data_size += sdu_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It was the last LI, then set data_size to full original PDU size */
|
||||
data_size = pdu_mngt->payload_size;
|
||||
}
|
||||
/* Go to next SDU */
|
||||
sdu_index ++;
|
||||
}
|
||||
else if (retx_so_start != 0)
|
||||
{
|
||||
/* in all other cases set fi_start to false if it SO Start is not 0 */
|
||||
fi_start = false;
|
||||
}
|
||||
|
||||
/* Set first SDU portion of the segment */
|
||||
sdus_segment_size[0] = data_size - retx_so_start;
|
||||
|
||||
/* Check if so end is in the first SDU portion */
|
||||
if (sdus_segment_size[0] >= retx_so_stop - retx_so_start + 1)
|
||||
{
|
||||
sdus_segment_size[0] = retx_so_stop - retx_so_start + 1;
|
||||
*payload_sizeP = sdus_segment_size[0];
|
||||
num_LIs_pdu_segment = 0;
|
||||
}
|
||||
|
||||
/* Bound first SDU segment to available TBS if necessary */
|
||||
if (sdus_segment_size[0] + RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE >= rlc_pP->nb_bytes_requested_by_mac)
|
||||
{
|
||||
sdus_segment_size[0] = rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE;
|
||||
*payload_sizeP = sdus_segment_size[0];
|
||||
num_LIs_pdu_segment = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Now look for the end if it was not set previously */
|
||||
if (*payload_sizeP == 0)
|
||||
{
|
||||
sdu_segment_index ++;
|
||||
while ((sdu_index < pdu_mngt->nb_sdus) && (data_size < retx_so_stop + 1))
|
||||
{
|
||||
if (sdu_index < pdu_mngt->nb_sdus - 1)
|
||||
{
|
||||
temp_read = ((*pdu_original_header_p) << 8) | (*(pdu_original_header_p + 1));
|
||||
sdu_size = RLC_AM_PDU_GET_LI(temp_read,li_bit_offset);
|
||||
pdu_original_header_p += li_jump_offset;
|
||||
li_bit_offset ^= 0x4;
|
||||
li_jump_offset ^= 0x3;
|
||||
data_size += sdu_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sdu_size = pdu_mngt->payload_size - data_size;
|
||||
data_size = pdu_mngt->payload_size;
|
||||
}
|
||||
|
||||
sdus_segment_size[sdu_segment_index] = sdu_size;
|
||||
sdu_index ++;
|
||||
sdu_segment_index ++;
|
||||
}
|
||||
|
||||
|
||||
if (data_size > retx_so_stop + 1)
|
||||
{
|
||||
sdus_segment_size[sdu_segment_index - 1] = retx_so_stop - (data_size - sdu_size) + 1;
|
||||
}
|
||||
|
||||
/* Set number of LIs in the segment */
|
||||
num_LIs_pdu_segment = sdu_segment_index - 1;
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.779
|
||||
if(num_LIs_pdu_segment > pdu_mngt->nb_sdus - 1)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Tx PDU Segment Data Error: nbLISegment=%d nbLIPDU=%d sn=%d LcId=%d !\n",
|
||||
num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (num_LIs_pdu_segment <= pdu_mngt->nb_sdus - 1, "RLC AM Tx PDU Segment Data Error: nbLISegment=%d nbLIPDU=%d sn=%d LcId=%d !\n",
|
||||
num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
/* Bound to available TBS taking into account min PDU segment header*/
|
||||
sdu_segment_index = 0;
|
||||
while ((sdu_segment_index < num_LIs_pdu_segment + 1) && (rlc_pP->nb_bytes_requested_by_mac > *payload_sizeP + RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index)))
|
||||
{
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.780
|
||||
if(sdus_segment_size[sdu_segment_index] <= 0)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM Tx PDU Segment Data Error: EMpty LI index=%d numLISegment=%d numLIPDU=%d PDULength=%d SOStart=%d SOStop=%d sn=%d LcId=%d !\n",
|
||||
sdu_segment_index,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,pdu_mngt->payload_size,retx_so_start,retx_so_stop,sn,rlc_pP->channel_id);
|
||||
sdu_segment_index++;
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
AssertFatal (sdus_segment_size[sdu_segment_index] > 0, "RLC AM Tx PDU Segment Data Error: EMpty LI index=%d numLISegment=%d numLIPDU=%d PDULength=%d SOStart=%d SOStop=%d sn=%d LcId=%d !\n",
|
||||
sdu_segment_index,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,pdu_mngt->payload_size,retx_so_start,retx_so_stop,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
/* Add next sdu_segment_index to data part */
|
||||
if (RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index) + (*payload_sizeP) + sdus_segment_size[sdu_segment_index] <= rlc_pP->nb_bytes_requested_by_mac)
|
||||
{
|
||||
(*payload_sizeP) += sdus_segment_size[sdu_segment_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bound to available TBS size */
|
||||
sdus_segment_size[sdu_segment_index] = rlc_pP->nb_bytes_requested_by_mac - RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index) - (*payload_sizeP);
|
||||
(*payload_sizeP) += sdus_segment_size[sdu_segment_index];
|
||||
}
|
||||
header_segment_length = RLC_AM_PDU_SEGMENT_HEADER_SIZE(sdu_segment_index);
|
||||
sdu_segment_index ++;
|
||||
}
|
||||
|
||||
num_LIs_pdu_segment = sdu_segment_index - 1;
|
||||
}
|
||||
|
||||
|
||||
/* update retx_so_stop */
|
||||
retx_so_stop = retx_so_start + (*payload_sizeP) - 1;
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.781
|
||||
if((retx_so_stop > pdu_mngt->payload_size - 1) || (retx_so_stop - retx_so_start + 1 >= pdu_mngt->payload_size))
|
||||
{
|
||||
LOG_E(RLC,"RLC AM Tx PDU Segment Data Error: retx_so_stop=%d OriginalPDUDataLength=%d SOStart=%d SegmentLength=%d numLISegment=%d numLIPDU=%d sn=%d LcId=%d !\n",
|
||||
retx_so_stop,pdu_mngt->payload_size,retx_so_start,*payload_sizeP,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal ((retx_so_stop <= pdu_mngt->payload_size - 1) && (retx_so_stop - retx_so_start + 1 < pdu_mngt->payload_size),
|
||||
"RLC AM Tx PDU Segment Data Error: retx_so_stop=%d OriginalPDUDataLength=%d SOStart=%d SegmentLength=%d numLISegment=%d numLIPDU=%d sn=%d LcId=%d !\n",
|
||||
retx_so_stop,pdu_mngt->payload_size,retx_so_start,*payload_sizeP,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
/* init FI End to false if retx_so_stop is not end of PDU */
|
||||
if (retx_so_stop != pdu_mngt->payload_size - 1)
|
||||
{
|
||||
fi_end = false;
|
||||
}
|
||||
|
||||
/* Check consistency between sdus_segment_size and payload_sizeP */
|
||||
/* And Set FI End if retx_so_stop = cumulated data size and this is not last SDU */
|
||||
data_size = 0;
|
||||
for (int i = 0; i < num_LIs_pdu_segment + 1; i++)
|
||||
{
|
||||
data_size += sdus_segment_size[i];
|
||||
if ((retx_so_stop == data_size - 1) && (i < num_LIs_pdu_segment))
|
||||
{
|
||||
fi_end = true;
|
||||
}
|
||||
}
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.782
|
||||
if(data_size != *payload_sizeP)
|
||||
{
|
||||
LOG_E(RLC,"RLC AM Tx PDU Segment Data Error: SduSum=%d Data=%d sn=%d LcId=%d !\n",
|
||||
data_size,*payload_sizeP,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (data_size == *payload_sizeP, "RLC AM Tx PDU Segment Data Error: SduSum=%d Data=%d sn=%d LcId=%d !\n",
|
||||
data_size,*payload_sizeP,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
|
||||
|
||||
/* Allocation */
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.783
|
||||
if(header_segment_length + *payload_sizeP > pdu_mngt->header_and_payload_size + 2)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM PDU Segment Error: Hdr=%d Data=%d Original Hdr+Data =%d sn=%d LcId=%d !\n",
|
||||
header_segment_length,*payload_sizeP,pdu_mngt->header_and_payload_size,sn,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal (header_segment_length + *payload_sizeP <= pdu_mngt->header_and_payload_size + 2, "RLC AM PDU Segment Error: Hdr=%d Data=%d Original Hdr+Data =%d sn=%d LcId=%d !\n",
|
||||
header_segment_length,*payload_sizeP,pdu_mngt->header_and_payload_size,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
mem_pdu_segment_p = get_free_mem_block((*payload_sizeP + header_segment_length + sizeof(struct mac_tb_req)), __func__);
|
||||
if(mem_pdu_segment_p == NULL) return NULL;
|
||||
pdu_segment_header_p = (uint8_t *)&mem_pdu_segment_p->data[sizeof(struct mac_tb_req)];
|
||||
((struct mac_tb_req*)(mem_pdu_segment_p->data))->data_ptr = pdu_segment_header_p;
|
||||
((struct mac_tb_req*)(mem_pdu_segment_p->data))->tb_size = header_segment_length + *payload_sizeP;
|
||||
|
||||
/* clear all PDU segment */
|
||||
memset(pdu_segment_header_p, 0, *payload_sizeP + header_segment_length);
|
||||
/* copy data part */
|
||||
memcpy(pdu_segment_header_p + header_segment_length, pdu_mngt->payload + retx_so_start, *payload_sizeP);
|
||||
}
|
||||
|
||||
/* Last step : update contexts and fill PDU Segment Header */
|
||||
if (mem_pdu_segment_p != NULL)
|
||||
{
|
||||
/* Update PDU Segment contexts */
|
||||
if (*payload_sizeP == pdu_mngt->hole_so_stop[pdu_mngt->retx_hole_index] - pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index] + 1)
|
||||
{
|
||||
/* All data in the segment are transmitted : switch to next one */
|
||||
pdu_mngt->retx_hole_index ++;
|
||||
if (pdu_mngt->retx_hole_index < pdu_mngt->num_holes)
|
||||
{
|
||||
/* Set min SOStart to the value of next hole : assumption is holes are ordered by increasing SOStart */
|
||||
pdu_mngt->nack_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no more scheduled Retx: reset values */
|
||||
/* Retx size is reset in the calling function */
|
||||
pdu_mngt->num_holes = 0;
|
||||
pdu_mngt->retx_hole_index = 0;
|
||||
pdu_mngt->nack_so_start = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not all segment data could be transmitted, just update SoStart */
|
||||
pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index] += (*payload_sizeP);
|
||||
pdu_mngt->nack_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index];
|
||||
}
|
||||
|
||||
/* Content is supposed to be init with 0 so with FIStart=FIEnd=true */
|
||||
RLC_AM_PDU_SET_D_C(*pdu_segment_header_p);
|
||||
RLC_AM_PDU_SET_RF(*pdu_segment_header_p);
|
||||
/* Change FI */
|
||||
if (!fi_start)
|
||||
{
|
||||
// Set to not starting
|
||||
(*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET + 1));
|
||||
}
|
||||
if (!fi_end)
|
||||
{
|
||||
// Set to not starting
|
||||
(*pdu_segment_header_p) |= (1 << (RLC_AM_PDU_FI_OFFSET));
|
||||
}
|
||||
/* Set SN */
|
||||
(*pdu_segment_header_p) |= ((sn >> 8) & 0x3);
|
||||
(*(pdu_segment_header_p + 1)) |= (sn & 0xFF);
|
||||
|
||||
/* Segment Offset */
|
||||
header_so_part = retx_so_start;
|
||||
|
||||
/* Last Segment Flag (LSF) */
|
||||
if (retx_so_stop == pdu_mngt->payload_size - 1)
|
||||
{
|
||||
RLC_AM_PDU_SET_LSF(header_so_part);
|
||||
}
|
||||
|
||||
/* Store SO bytes */
|
||||
* (pdu_segment_header_p + 2) = (header_so_part >> 8) & 0xFF;
|
||||
* (pdu_segment_header_p + 3) = header_so_part & 0xFF;
|
||||
|
||||
/* Fill LI part */
|
||||
if (num_LIs_pdu_segment)
|
||||
{
|
||||
uint16_t index = 0;
|
||||
uint16_t temp = 0;
|
||||
/* Set Extension bit in first byte */
|
||||
RLC_AM_PDU_SET_E(*pdu_segment_header_p);
|
||||
|
||||
/* loop on nb of LIs */
|
||||
pdu_segment_header_p += RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE;
|
||||
li_bit_offset = 4; /* toggle between 0 and 4 */
|
||||
li_jump_offset = 1; /* toggle between 1 and 2 */
|
||||
|
||||
while (index < num_LIs_pdu_segment)
|
||||
{
|
||||
/* Set E bit for next LI if present */
|
||||
if (index < num_LIs_pdu_segment - 1)
|
||||
RLC_SET_BIT(temp,li_bit_offset + RLC_AM_LI_BITS);
|
||||
/* Set LI */
|
||||
RLC_AM_PDU_SET_LI(temp,sdus_segment_size[index],li_bit_offset);
|
||||
*pdu_segment_header_p = temp >> 8;
|
||||
*(pdu_segment_header_p + 1) = temp & 0xFF;
|
||||
pdu_segment_header_p += li_jump_offset;
|
||||
li_bit_offset ^= 0x4;
|
||||
li_jump_offset ^= 0x3;
|
||||
|
||||
temp = ((*pdu_segment_header_p) << 8) | (*(pdu_segment_header_p + 1));
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RE-SEGMENT] OUT OF MEMORY PDU SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sn);
|
||||
}
|
||||
|
||||
return mem_pdu_segment_p;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_tx_buffer_display (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP,
|
||||
char* const message_pP)
|
||||
{
|
||||
rlc_sn_t sn = rlc_pP->vt_a;
|
||||
int i, loop = 0;
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p;
|
||||
|
||||
if (message_pP) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" Retransmission buffer %s VT(A)=%04d VT(S)=%04d:",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
message_pP,
|
||||
rlc_pP->vt_a,
|
||||
rlc_pP->vt_s);
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" Retransmission buffer VT(A)=%04d VT(S)=%04d:",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vt_a,
|
||||
rlc_pP->vt_s);
|
||||
}
|
||||
|
||||
while (rlc_pP->vt_s != sn) {
|
||||
tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE];
|
||||
if (tx_data_pdu_buffer_p->mem_block) {
|
||||
if ((loop % 1) == 0) {
|
||||
LOG_D(RLC, "\nTX SN:\t");
|
||||
}
|
||||
|
||||
if (tx_data_pdu_buffer_p->flags.retransmit) {
|
||||
LOG_D(RLC, "%04d %d/%d Bytes (NACK RTX:%02d ",sn, tx_data_pdu_buffer_p->header_and_payload_size, tx_data_pdu_buffer_p->payload_size,
|
||||
tx_data_pdu_buffer_p->retx_count);
|
||||
} else {
|
||||
LOG_D(RLC, "%04d %d/%d Bytes (RTX:%02d ",sn, tx_data_pdu_buffer_p->header_and_payload_size, tx_data_pdu_buffer_p->payload_size,
|
||||
tx_data_pdu_buffer_p->retx_count);
|
||||
}
|
||||
|
||||
if (tx_data_pdu_buffer_p->num_holes == 0) {
|
||||
LOG_D(RLC, "SO:%04d->%04d)\t", tx_data_pdu_buffer_p->nack_so_start, tx_data_pdu_buffer_p->nack_so_stop);
|
||||
} else {
|
||||
for (i=0; i<tx_data_pdu_buffer_p->num_holes; i++) {
|
||||
//assert(i < RLC_AM_MAX_HOLES_REPORT_PER_PDU);
|
||||
if(i >= RLC_AM_MAX_HOLES_REPORT_PER_PDU) {
|
||||
LOG_E(RLC, "num_holes error. %d %d %d\n", tx_data_pdu_buffer_p->num_holes, i, RLC_AM_MAX_HOLES_REPORT_PER_PDU);
|
||||
break;
|
||||
}
|
||||
LOG_D(RLC, "SO:%04d->%04d)\t", tx_data_pdu_buffer_p->hole_so_start[i], tx_data_pdu_buffer_p->hole_so_stop[i]);
|
||||
}
|
||||
}
|
||||
|
||||
loop++;
|
||||
}
|
||||
|
||||
sn = (sn + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
|
||||
LOG_D(RLC, "\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
mem_block_t * rlc_am_get_pdu_to_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP)
|
||||
{
|
||||
rlc_sn_t sn = rlc_pP->vt_a;
|
||||
rlc_sn_t sn_end = rlc_pP->vt_s;
|
||||
mem_block_t* pdu_p = NULL;
|
||||
mem_block_t* mb_p = NULL;
|
||||
rlc_am_tx_data_pdu_management_t* tx_data_pdu_management;
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.769
|
||||
if((rlc_pP->retrans_num_pdus <= 0) || (rlc_pP->vt_a == rlc_pP->vt_s))
|
||||
{
|
||||
LOG_E(RLC, "RLC AM ReTx start process Error: NbPDUtoRetx=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
rlc_pP->retrans_num_pdus,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
AssertFatal ((rlc_pP->retrans_num_pdus > 0) && (rlc_pP->vt_a != rlc_pP->vt_s), "RLC AM ReTx start process Error: NbPDUtoRetx=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
rlc_pP->retrans_num_pdus,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
do
|
||||
{
|
||||
tx_data_pdu_management = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE];
|
||||
if ((tx_data_pdu_management->flags.retransmit) && (tx_data_pdu_management->flags.max_retransmit == 0))
|
||||
{
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.770
|
||||
if(tx_data_pdu_management->sn != sn)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM ReTx PDU Error: SN Error pdu_sn=%d sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
tx_data_pdu_management->sn,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
}
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.771
|
||||
else if(tx_data_pdu_management->flags.transmitted != 1)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM ReTx PDU Error: State Error sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
}
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.772
|
||||
else if(tx_data_pdu_management->retx_payload_size <= 0)
|
||||
{
|
||||
LOG_E(RLC, "RLC AM ReTx PDU Error: No Data to Retx sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
AssertFatal (tx_data_pdu_management->sn == sn, "RLC AM ReTx PDU Error: SN Error pdu_sn=%d sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
tx_data_pdu_management->sn,sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
AssertFatal (tx_data_pdu_management->flags.transmitted == 1, "RLC AM ReTx PDU Error: State Error sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
AssertFatal (tx_data_pdu_management->retx_payload_size > 0, "RLC AM ReTx PDU Error: No Data to Retx sn=%d vtA=%d vtS=%d LcId=%d !\n",
|
||||
sn,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
*/
|
||||
/* Either the whole RLC PDU is to be transmitted and there is enough MAC TBS or there is minimum TBS size for transmitting 1 AM PDU segment */
|
||||
if ((tx_data_pdu_management->retx_payload_size == tx_data_pdu_management->payload_size) && (rlc_pP->nb_bytes_requested_by_mac >= tx_data_pdu_management->header_and_payload_size))
|
||||
{
|
||||
/* check maxretx is not hit */
|
||||
if (tx_data_pdu_management->retx_count_next <= rlc_pP->max_retx_threshold)
|
||||
{
|
||||
pdu_p = rlc_am_retransmit_get_copy(ctxt_pP, rlc_pP, sn);
|
||||
|
||||
if (pdu_p != NULL)
|
||||
{
|
||||
rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size;
|
||||
rlc_pP->retrans_num_pdus --;
|
||||
tx_data_pdu_management->retx_payload_size = 0;
|
||||
tx_data_pdu_management->flags.retransmit = 0;
|
||||
|
||||
// update stats
|
||||
rlc_pP->stat_tx_data_pdu += 1;
|
||||
rlc_pP->stat_tx_retransmit_pdu += 1;
|
||||
rlc_pP->stat_tx_retransmit_pdu_by_status += 1;
|
||||
rlc_pP->stat_tx_data_bytes += tx_data_pdu_management->payload_size;
|
||||
rlc_pP->stat_tx_retransmit_bytes += tx_data_pdu_management->payload_size;
|
||||
rlc_pP->stat_tx_retransmit_bytes_by_status += tx_data_pdu_management->payload_size;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TO DO : RLC Notification to RRC + ReEstablishment procedure
|
||||
tx_data_pdu_management->flags.max_retransmit = 1;
|
||||
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RLC AM MAX RETX=%d] SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
tx_data_pdu_management->retx_count_next,
|
||||
sn);
|
||||
mb_p = rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE].mem_block;
|
||||
if(mb_p != NULL){
|
||||
free_mem_block(mb_p, __func__);
|
||||
tx_data_pdu_management->mem_block = NULL;
|
||||
tx_data_pdu_management->flags.retransmit = 0;
|
||||
tx_data_pdu_management->flags.ack = 1;
|
||||
tx_data_pdu_management->flags.transmitted = 0;
|
||||
rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size;
|
||||
tx_data_pdu_management->retx_payload_size = 0;
|
||||
tx_data_pdu_management->num_holes = 0;
|
||||
rlc_pP->retrans_num_pdus --;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rlc_pP->nb_bytes_requested_by_mac >= 5)
|
||||
{
|
||||
/* Resegmentation case */
|
||||
/* check maxretx is not hit */
|
||||
if (tx_data_pdu_management->retx_count_next <= rlc_pP->max_retx_threshold)
|
||||
{
|
||||
sdu_size_t pdu_data_size = 0;
|
||||
|
||||
pdu_p = rlc_am_retransmit_get_am_segment(ctxt_pP, rlc_pP, tx_data_pdu_management,&pdu_data_size);
|
||||
|
||||
if (pdu_p != NULL)
|
||||
{
|
||||
//Assertion(eNB)_PRAN_DesignDocument_annex No.773
|
||||
if((tx_data_pdu_management->retx_payload_size < pdu_data_size)|| (rlc_pP->retrans_num_bytes_to_retransmit < pdu_data_size))
|
||||
{
|
||||
LOG_E(RLC, "RLC AM ReTx PDU Segment Error: DataSize=%d PDUReTxsize=%d TotalReTxsize=%d sn=%d LcId=%d !\n",
|
||||
pdu_data_size,tx_data_pdu_management->retx_payload_size,rlc_pP->retrans_num_bytes_to_retransmit,sn,rlc_pP->channel_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
AssertFatal ((tx_data_pdu_management->retx_payload_size >= pdu_data_size) && (rlc_pP->retrans_num_bytes_to_retransmit >= pdu_data_size), "RLC AM ReTx PDU Segment Error: DataSize=%d PDUReTxsize=%d TotalReTxsize=%d sn=%d LcId=%d !\n",
|
||||
pdu_data_size,tx_data_pdu_management->retx_payload_size,rlc_pP->retrans_num_bytes_to_retransmit,sn,rlc_pP->channel_id);
|
||||
*/
|
||||
tx_data_pdu_management->retx_payload_size -= pdu_data_size;
|
||||
rlc_pP->retrans_num_bytes_to_retransmit -= pdu_data_size;
|
||||
if (tx_data_pdu_management->retx_payload_size == 0)
|
||||
{
|
||||
rlc_pP->retrans_num_pdus --;
|
||||
tx_data_pdu_management->retx_payload_size = 0;
|
||||
tx_data_pdu_management->flags.retransmit = 0;
|
||||
}
|
||||
|
||||
// update stats
|
||||
rlc_pP->stat_tx_data_pdu += 1;
|
||||
rlc_pP->stat_tx_retransmit_pdu += 1;
|
||||
rlc_pP->stat_tx_retransmit_pdu_by_status += 1;
|
||||
rlc_pP->stat_tx_data_bytes += pdu_data_size;
|
||||
rlc_pP->stat_tx_retransmit_bytes += pdu_data_size;
|
||||
rlc_pP->stat_tx_retransmit_bytes_by_status += pdu_data_size;
|
||||
|
||||
}//Assertion(eNB)_PRAN_DesignDocument_annex No.773
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TO DO : RLC Notification to RRC + ReEstablishment procedure
|
||||
tx_data_pdu_management->flags.max_retransmit = 1;
|
||||
LOG_W(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RLC AM MAX RETX=%d] SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
tx_data_pdu_management->retx_count_next,
|
||||
sn);
|
||||
mb_p = rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE].mem_block;
|
||||
if(mb_p != NULL){
|
||||
free_mem_block(mb_p, __func__);
|
||||
tx_data_pdu_management->mem_block = NULL;
|
||||
tx_data_pdu_management->flags.retransmit = 0;
|
||||
tx_data_pdu_management->flags.ack = 1;
|
||||
tx_data_pdu_management->flags.transmitted = 0;
|
||||
rlc_pP->retrans_num_bytes_to_retransmit -= tx_data_pdu_management->retx_payload_size;
|
||||
tx_data_pdu_management->retx_payload_size = 0;
|
||||
tx_data_pdu_management->num_holes = 0;
|
||||
rlc_pP->retrans_num_pdus --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pdu_p != NULL)
|
||||
{
|
||||
/* check polling */
|
||||
rlc_am_pdu_sn_10_t* pdu_header_p = (rlc_am_pdu_sn_10_t*) (&pdu_p->data[sizeof(struct mac_tb_req)]);
|
||||
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_header_p, tx_data_pdu_management->payload_size,false);
|
||||
|
||||
tx_data_pdu_management->retx_count = tx_data_pdu_management->retx_count_next;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}//Assertion(eNB)_PRAN_DesignDocument_annex No.770 No.771 No.772
|
||||
}
|
||||
sn = RLC_AM_NEXT_SN(sn);
|
||||
} while((sn != sn_end) && (rlc_pP->retrans_num_pdus > 0));
|
||||
|
||||
return pdu_p;
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_retransmit.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the retransmission.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_retransmit_impl_ RLC AM Retransmitter Internal Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_AM_RETRANSMIT_H__
|
||||
# define __RLC_AM_RETRANSMIT_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn bool rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, int16_t snP, int16_t prev_nack_snP,sdu_size_t so_startP, sdu_size_t so_endP)
|
||||
* \brief The RLC AM PDU which have the sequence number snP is marked NACKed with segment offset fields.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of the PDU that is negative acknowledged.
|
||||
* \param[in] prev_nack_snP Sequence number of previous PDU that is negative acknowledged.
|
||||
* \param[in] so_startP Start of the segment offset of the PDU that .
|
||||
* \param[in] so_endP Transport blocks received from MAC layer.
|
||||
* \return OK/KO
|
||||
* \note It may appear a new hole in the retransmission buffer depending on the segment offset informations. Depending on the state of the retransmission buffer, negative confirmation can be sent to higher layers about the drop by the RLC AM instance of a particular SDU.
|
||||
*/
|
||||
bool rlc_am_nack_pdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
const rlc_sn_t prev_nack_snP,
|
||||
sdu_size_t so_startP,
|
||||
sdu_size_t so_endP);
|
||||
|
||||
/*! \fn void rlc_am_ack_pdu (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP, rlc_sn_t snP)
|
||||
* \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of the PDU that is acknowledged.
|
||||
* \param[in] free_pdu Boolean indicating that the PDU can be freed because smaller than new vtA.
|
||||
* \note Depending on the state of the retransmission buffer, positive confirmation can be sent to higher layers about the receiving by the peer RLC AM instance of a particular SDU.
|
||||
*/
|
||||
void rlc_am_ack_pdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
bool free_pdu);
|
||||
|
||||
/*! \fn mem_block_t* rlc_am_retransmit_get_copy (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, rlc_sn_t snP)
|
||||
* \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of the PDU to be copied.
|
||||
* \return A copy of the PDU having sequence number equal to parameter snP.
|
||||
*/
|
||||
mem_block_t* rlc_am_retransmit_get_copy (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP);
|
||||
/*! \fn mem_block_t* rlc_am_retransmit_get_subsegment (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP,rlc_sn_t snP, sdu_size_t *sizeP)
|
||||
* \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of the PDU to be copied.
|
||||
* \param[in,out] sizeP Maximum size allowed for the subsegment, it is updated with the amount of bytes not used (sizeP[out] = sizeP[in] - size of segment).
|
||||
* \return A copy of a segment of the PDU having sequence number equal to parameter snP.
|
||||
*/
|
||||
mem_block_t* rlc_am_retransmit_get_subsegment (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
sdu_size_t *const sizeP);
|
||||
/*! \fn mem_block_t* rlc_am_get_pdu_to_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP)
|
||||
* \brief Find a PDU or PDU segment to retransmit.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \return A copy of the retransmitted PDU or PDU segment or NULL if TBS was not big enough
|
||||
*/
|
||||
mem_block_t* rlc_am_get_pdu_to_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
|
||||
rlc_am_entity_t* const rlcP);
|
||||
/*! \fn void rlc_am_retransmit_any_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* rlcP)
|
||||
* \brief Retransmit any PDU in order to unblock peer entity, if no suitable PDU is found (depending on requested MAC size) to be retransmitted, then try to retransmit a subsegment of any PDU.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_retransmit_any_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlcP);
|
||||
|
||||
/*! \fn void rlc_am_tx_buffer_display (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* rlcP, char* message_pP)
|
||||
* \brief Display the dump of the retransmission buffer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] message_pP Message to be displayed along with the display of the dump of the retransmission buffer.
|
||||
*/
|
||||
void rlc_am_tx_buffer_display (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlcP,
|
||||
char* const message_pP);
|
||||
/** @} */
|
||||
# endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_rx_list.h
|
||||
* \brief This file defines the prototypes of the functions dealing with a RX list data structure supporting re-segmentation.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_rx_list_impl_ RLC AM RX List Reference Implementation
|
||||
* @ingroup _rlc_am_internal_receiver_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __RLC_AM_RX_LIST_H__
|
||||
# define __RLC_AM_RX_LIST_H__
|
||||
|
||||
# include "UTIL/MEM/mem_block.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//#include "PHY/defs.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn rlc_am_rx_pdu_status_t rlc_am_rx_list_check_duplicate_insert_pdu(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,mem_block_t* const tb_pP)
|
||||
* \brief Insert a PDU in the RX buffer after removing byte duplicate (implemented with a list).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] tbP A PDU embedded in a mem_block_t.
|
||||
* \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted.
|
||||
*/
|
||||
rlc_am_rx_pdu_status_t rlc_am_rx_list_check_duplicate_insert_pdu(const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* const rlc_pP,mem_block_t* const tb_pP);
|
||||
|
||||
/*! \fn signed int rlc_am_rx_list_insert_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP , mem_block_t* const tbP)
|
||||
* \brief Insert a PDU in the RX buffer (implemented with a list).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] tbP A PDU embedded in a mem_block_t.
|
||||
* \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted.
|
||||
*/
|
||||
signed int rlc_am_rx_list_insert_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP);
|
||||
|
||||
/*! \fn bool rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Check if reassembly taking into account potential new vrR value
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \return true if reassembly must be done, false else
|
||||
*/
|
||||
bool rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_rx_check_all_byte_segments(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP)
|
||||
* \brief Check if all sub-segments of a PDU are received, if yes then call rlc_am_rx_mark_all_segments_received() procedure.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] tbP A PDU embedded in a mem_block_t.
|
||||
*/
|
||||
void rlc_am_rx_check_all_byte_segments(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP);
|
||||
|
||||
/*! \fn void rlc_am_rx_mark_all_segments_received (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const first_segment_tbP)
|
||||
* \brief Mark all PDUs having the same sequence number as first_segment_tbP with the information that all segments have been received.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] first_segment_tbP A PDU embedded in a mem_block_t, it is the first PDU in the RX buffer (list) that have its sequence number.
|
||||
*/
|
||||
void rlc_am_rx_mark_all_segments_received(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const first_segment_tbP);
|
||||
|
||||
/*! \fn void rlc_am_rx_list_reassemble_rlc_sdus(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP)
|
||||
* \brief Reassembly all SDUS that it is possible to reassembly by parsing the RX buffer and looking for PDUs having the flag 'all segments received'.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_rx_list_reassemble_rlc_sdus(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP);
|
||||
|
||||
/*! \fn mem_block_t* list2_insert_before_element (mem_block_t * element_to_insertP, mem_block_t * elementP, list2_t * listP)
|
||||
* \brief Insert a PDU embedded in a mem_block_t in a list at a position before a designated element of the list.
|
||||
* \param[in] element_to_insertP Element to insert in the list listP, before elementP position.
|
||||
* \param[in] elementP Element in the list.
|
||||
* \param[in] listP List where elements are linked.
|
||||
*/
|
||||
mem_block_t* list2_insert_before_element (mem_block_t * element_to_insertP, mem_block_t * elementP, list2_t * listP);
|
||||
|
||||
/*! \fn mem_block_t* list2_insert_after_element (mem_block_t * element_to_insertP, mem_block_t * elementP, list2_t * listP)
|
||||
* \brief Insert a PDU embedded in a mem_block_t in a list at a position after a designated element of the list.
|
||||
* \param[in] element_to_insertP Element to insert in the list listP, after elementP position.
|
||||
* \param[in] elementP Element in the list.
|
||||
* \param[in] listP List where elements are linked.
|
||||
*/
|
||||
mem_block_t* list2_insert_after_element (mem_block_t * element_to_insertP, mem_block_t * elementP, list2_t * listP);
|
||||
|
||||
/*! \fn void rlc_am_rx_list_display (const rlc_am_entity_t* const rlcP, char* messageP)
|
||||
* \brief Display the dump of the RX buffer.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] messageP Message to be displayed along with the display of the dump of the RX buffer.
|
||||
*/
|
||||
void rlc_am_rx_list_display (const rlc_am_entity_t* const rlcP, char* messageP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,566 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_SEGMENT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <assert.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "list.h"
|
||||
#include "rlc_am.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_pdu_polling(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t *const pdu_pP,
|
||||
const int16_t payload_sizeP,
|
||||
bool is_new_pdu)
|
||||
{
|
||||
// 5.2.2 Polling
|
||||
// An AM RLC entity can poll its peer AM RLC entity in order to trigger STATUS reporting at the peer AM RLC entity.
|
||||
// 5.2.2.1 Transmission of a AMD PDU or AMD PDU segment
|
||||
// Upon assembly of a new AMD PDU, the transmitting side of an AM RLC entity shall:
|
||||
// - increment PDU_WITHOUT_POLL by one;
|
||||
// - increment BYTE_WITHOUT_POLL by every new byte of Data field element that it maps to the Data field of
|
||||
// the RLC data PDU;
|
||||
// - if PDU_WITHOUT_POLL >= pollPDU; or
|
||||
// - if BYTE_WITHOUT_POLL >= pollByte;
|
||||
// -include a poll in the RLC data PDU as described below.
|
||||
// Upon assembly of an AMD PDU or AMD PDU segment, the transmitting side of an AM RLC entity shall:
|
||||
// - if both the transmission buffer and the retransmission buffer becomes empty (excluding transmitted RLC data
|
||||
// PDU awaiting for acknowledgements) after the transmission of the RLC data PDU; or
|
||||
// - if no new RLC data PDU can be transmitted after the transmission of the RLC data PDU (e.g. due to window
|
||||
// stalling);
|
||||
// - include a poll in the RLC data PDU as described below.
|
||||
// To include a poll in a RLC data PDU, the transmitting side of an AM RLC entity shall:
|
||||
// - set the P field of the RLC data PDU to "1";
|
||||
// - set PDU_WITHOUT_POLL to 0;
|
||||
// - set BYTE_WITHOUT_POLL to 0;
|
||||
// After delivering a RLC data PDU including a poll to lower layer and after incrementing of VT(S) if necessary, the
|
||||
// transmitting side of an AM RLC entity shall:
|
||||
// - set POLL_SN to VT(S) – 1;
|
||||
// - if t-PollRetransmit is not running:
|
||||
// - start t-PollRetransmit;
|
||||
// - else:
|
||||
// - restart t-PollRetransmit;
|
||||
|
||||
if (is_new_pdu) {
|
||||
if (rlc_pP->poll_pdu != RLC_AM_POLL_PDU_INFINITE) {
|
||||
rlc_pP->c_pdu_without_poll += 1;
|
||||
}
|
||||
|
||||
if (rlc_pP->poll_byte != RLC_AM_POLL_BYTE_INFINITE) {
|
||||
rlc_pP->c_byte_without_poll += payload_sizeP;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
((is_new_pdu) && ((rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) ||
|
||||
(rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte))) ||
|
||||
((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
|
||||
(rlc_pP->vt_s == rlc_pP->vt_ms) ||
|
||||
(rlc_pP->force_poll == true)
|
||||
) {
|
||||
rlc_pP->force_poll = false;
|
||||
|
||||
if ((is_new_pdu) && (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu)) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM PDU THRESHOLD %d HAS BEEN REACHED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->poll_pdu);
|
||||
}
|
||||
if ((is_new_pdu) && (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte)) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX NUM BYTES THRESHOLD %d HAS BEEN REACHED\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->poll_byte);
|
||||
}
|
||||
if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE TX BUFFERS ARE EMPTY\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
if (rlc_pP->vt_s == rlc_pP->vt_ms) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[POLL] SET POLL BECAUSE OF WINDOW STALLING\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
|
||||
RLC_AM_PDU_SET_POLL(pdu_pP->b1);
|
||||
rlc_pP->c_pdu_without_poll = 0;
|
||||
rlc_pP->c_byte_without_poll = 0;
|
||||
|
||||
// vt_s shall have been updated before in case of new transmission
|
||||
rlc_pP->poll_sn = RLC_AM_PREV_SN(rlc_pP->vt_s);
|
||||
//optimisation if (!rlc_pP->t_poll_retransmit.running) {
|
||||
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
|
||||
//optimisation } else {
|
||||
//optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out;
|
||||
//optimisation }
|
||||
} else {
|
||||
// Need to clear poll bit as it may be a copy(retransmission case) of the original RLC PDU which was containing a poll
|
||||
RLC_AM_PDU_CLEAR_POLL(pdu_pP->b1);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_segment_10 (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP)
|
||||
{
|
||||
list_t pdus;
|
||||
sdu_size_t pdu_remaining_size = 0;
|
||||
sdu_size_t test_pdu_remaining_size = 0;
|
||||
|
||||
sdu_size_t nb_bytes_to_transmit = rlc_pP->nb_bytes_requested_by_mac;
|
||||
rlc_am_pdu_sn_10_t *pdu_p = NULL;
|
||||
struct mac_tb_req *pdu_tb_req_p = NULL;
|
||||
mem_block_t *pdu_mem_p = NULL;
|
||||
unsigned char *data = NULL;
|
||||
unsigned char *data_sdu_p = NULL;
|
||||
rlc_am_e_li_t *e_li_p = NULL;
|
||||
rlc_am_tx_sdu_management_t *sdu_mngt_p = NULL;
|
||||
rlc_am_tx_data_pdu_management_t *pdu_mngt_p = NULL;
|
||||
|
||||
sdu_size_t li_length_in_bytes = 0;
|
||||
sdu_size_t test_li_length_in_bytes = 0;
|
||||
sdu_size_t test_remaining_size_to_substract= 0;
|
||||
unsigned int test_remaining_num_li_to_substract = 0;
|
||||
unsigned int continue_fill_pdu_with_sdu = 0;
|
||||
unsigned int num_fill_sdu = 0;
|
||||
unsigned int test_num_li = 0;
|
||||
unsigned int fill_num_li = 0;
|
||||
unsigned int sdu_buffer_index = 0;
|
||||
sdu_size_t data_pdu_size = 0;
|
||||
|
||||
unsigned int fi_first_byte_pdu_is_first_byte_sdu = 0;
|
||||
unsigned int fi_last_byte_pdu_is_last_byte_sdu = 0;
|
||||
unsigned int fi = 0;
|
||||
signed int max_li_overhead = 0;
|
||||
|
||||
LOG_T(RLC,
|
||||
PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] rlc_pP->current_sdu_index %d rlc_pP->next_sdu_index %d rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block %p sdu_buffer_occupancy %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->current_sdu_index,
|
||||
rlc_pP->next_sdu_index,
|
||||
rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block,
|
||||
rlc_pP->sdu_buffer_occupancy);
|
||||
|
||||
if (rlc_pP->sdu_buffer_occupancy <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//msg ("[FRAME %05d][%s][RLC_AM][MOD %u/%u][RB %u][SEGMENT]\n", rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame);
|
||||
list_init (&pdus, NULL); // param string identifying the list is NULL
|
||||
pdu_mem_p = NULL;
|
||||
|
||||
|
||||
RLC_AM_MUTEX_LOCK(&rlc_pP->lock_input_sdus, ctxt_pP, rlc_pP);
|
||||
|
||||
while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block) && (nb_bytes_to_transmit > 0) ) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] nb_bytes_to_transmit %d BO %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
nb_bytes_to_transmit,
|
||||
rlc_pP->sdu_buffer_occupancy);
|
||||
|
||||
// pdu_p management
|
||||
if (!pdu_mem_p) {
|
||||
if (rlc_pP->nb_sdu_no_segmented <= 1) {
|
||||
max_li_overhead = 0;
|
||||
} else {
|
||||
/* This computation assumes there is no SDU with size greater than 2047 bytes, otherwise a new PDU must be built except for LI15 configuration from Rel12*/
|
||||
test_num_li = rlc_pP->nb_sdu_no_segmented - 1;
|
||||
max_li_overhead = test_num_li + (test_num_li >> 1) + (test_num_li & 1);
|
||||
}
|
||||
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
max_li_overhead);
|
||||
|
||||
if (nb_bytes_to_transmit >= (rlc_pP->sdu_buffer_occupancy + RLC_AM_HEADER_MIN_SIZE + max_li_overhead)) {
|
||||
data_pdu_size = rlc_pP->sdu_buffer_occupancy + RLC_AM_HEADER_MIN_SIZE + max_li_overhead;
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] alloc PDU size %d bytes to contain not all bytes requested by MAC but all BO of RLC@1\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
data_pdu_size);
|
||||
} else {
|
||||
data_pdu_size = nb_bytes_to_transmit;
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] alloc PDU size %d bytes to contain all bytes requested by MAC@1\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
data_pdu_size);
|
||||
}
|
||||
|
||||
if (!(pdu_mem_p = get_free_mem_block (data_pdu_size + sizeof(struct mac_tb_req), __func__))) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] ERROR COULD NOT GET NEW PDU, EXIT\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] get new PDU %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
data_pdu_size);
|
||||
pdu_remaining_size = data_pdu_size - RLC_AM_HEADER_MIN_SIZE;
|
||||
pdu_p = (rlc_am_pdu_sn_10_t*) (&pdu_mem_p->data[sizeof(struct mac_tb_req)]);
|
||||
pdu_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data);
|
||||
pdu_mngt_p = &rlc_pP->tx_data_pdu_buffer[rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE];
|
||||
memset(pdu_mngt_p, 0, sizeof (rlc_am_tx_data_pdu_management_t));
|
||||
|
||||
memset (pdu_mem_p->data, 0, sizeof (rlc_am_pdu_sn_10_t)+sizeof(struct mac_tb_req));
|
||||
li_length_in_bytes = 1;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// compute how many SDUS can fill the PDU
|
||||
//----------------------------------------
|
||||
continue_fill_pdu_with_sdu = 1;
|
||||
num_fill_sdu = 0;
|
||||
test_num_li = 0;
|
||||
sdu_buffer_index = rlc_pP->current_sdu_index;
|
||||
test_pdu_remaining_size = pdu_remaining_size;
|
||||
test_li_length_in_bytes = 1;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
|
||||
|
||||
while ((rlc_pP->input_sdus[sdu_buffer_index].mem_block) && (continue_fill_pdu_with_sdu > 0)) {
|
||||
sdu_mngt_p = &rlc_pP->input_sdus[sdu_buffer_index];
|
||||
|
||||
if (sdu_mngt_p->sdu_remaining_size > test_pdu_remaining_size) {
|
||||
// no LI
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = 0;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
} else if (sdu_mngt_p->sdu_remaining_size == test_pdu_remaining_size) {
|
||||
// fi will indicate end of PDU is end of SDU, no need for LI
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = 0;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) == test_pdu_remaining_size ) {
|
||||
// no LI
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = 0;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
pdu_remaining_size = pdu_remaining_size - (test_li_length_in_bytes ^ 3);
|
||||
} else if ((sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3)) < test_pdu_remaining_size ) {
|
||||
if (pdu_mngt_p->nb_sdus >= (RLC_AM_MAX_SDU_IN_PDU-1)) {
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
//num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = 0;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
pdu_remaining_size = pdu_remaining_size - 1;
|
||||
} else {
|
||||
test_num_li += 1;
|
||||
num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = test_pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + (test_li_length_in_bytes ^ 3));
|
||||
test_remaining_size_to_substract = test_li_length_in_bytes ^ 3;
|
||||
test_remaining_num_li_to_substract = 1;
|
||||
test_li_length_in_bytes = test_li_length_in_bytes ^ 3;
|
||||
}
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] sdu_mngt_p->sdu_remaining_size=%d test_pdu_remaining_size=%d test_li_length_in_bytes=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p->sdu_remaining_size,
|
||||
test_pdu_remaining_size,
|
||||
test_li_length_in_bytes ^ 3);
|
||||
// reduce the size of the PDU
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
num_fill_sdu += 1;
|
||||
test_pdu_remaining_size = 0;
|
||||
test_remaining_size_to_substract = 0;
|
||||
test_remaining_num_li_to_substract = 0;
|
||||
pdu_remaining_size = pdu_remaining_size - 1;
|
||||
}
|
||||
|
||||
pdu_mngt_p->sdus_index[pdu_mngt_p->nb_sdus++] = sdu_buffer_index;
|
||||
sdu_mngt_p->pdus_index[sdu_mngt_p->nb_pdus++] = rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE;
|
||||
//assert(sdu_mngt_p->nb_pdus < RLC_AM_MAX_SDU_FRAGMENTS);
|
||||
if(sdu_mngt_p->nb_pdus >= RLC_AM_MAX_SDU_FRAGMENTS) {
|
||||
LOG_E(RLC,PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] loop error. %d %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), sdu_mngt_p->nb_pdus, RLC_AM_MAX_SDU_FRAGMENTS);
|
||||
break;
|
||||
}
|
||||
sdu_buffer_index = (sdu_buffer_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (test_remaining_num_li_to_substract > 0) {
|
||||
// there is a LI that is not necessary
|
||||
test_num_li = test_num_li - 1;
|
||||
pdu_remaining_size = pdu_remaining_size - test_remaining_size_to_substract;
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
// Do the real filling of the pdu_p
|
||||
//----------------------------------------
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT" data shift %d Bytes num_li %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
((test_num_li*3) +1) >> 1,
|
||||
test_num_li);
|
||||
data = ((unsigned char*)(&pdu_p->data[((test_num_li*3) +1) >> 1]));
|
||||
pdu_mngt_p->payload = data;
|
||||
e_li_p = (rlc_am_e_li_t*)(pdu_p->data);
|
||||
continue_fill_pdu_with_sdu = 1;
|
||||
li_length_in_bytes = 1;
|
||||
fill_num_li = 0;
|
||||
fi_first_byte_pdu_is_first_byte_sdu = 0;
|
||||
fi_last_byte_pdu_is_last_byte_sdu = 0;
|
||||
|
||||
if (rlc_pP->input_sdus[rlc_pP->current_sdu_index].sdu_remaining_size ==
|
||||
rlc_pP->input_sdus[rlc_pP->current_sdu_index].sdu_size) {
|
||||
fi_first_byte_pdu_is_first_byte_sdu = 1;
|
||||
}
|
||||
|
||||
while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index].mem_block) && (continue_fill_pdu_with_sdu > 0)) {
|
||||
sdu_mngt_p = &rlc_pP->input_sdus[rlc_pP->current_sdu_index];
|
||||
|
||||
if (sdu_mngt_p->sdu_segmented_size == 0) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] GET NEW SDU %p AVAILABLE SIZE %d Bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p,
|
||||
sdu_mngt_p->sdu_remaining_size);
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] GET AGAIN SDU %p REMAINING AVAILABLE SIZE %d Bytes / %d Bytes LENGTH \n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p,
|
||||
sdu_mngt_p->sdu_remaining_size,
|
||||
sdu_mngt_p->sdu_size);
|
||||
}
|
||||
|
||||
data_sdu_p = &sdu_mngt_p->first_byte[sdu_mngt_p->sdu_segmented_size];
|
||||
|
||||
if (sdu_mngt_p->sdu_remaining_size > pdu_remaining_size) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling all remaining PDU with %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_remaining_size);
|
||||
//msg ("[FRAME %05d][%s][RLC_AM][MOD %u/%u][RB %u][SEGMENT] pdu_mem_p %p pdu_p %p pdu_p->data %p data %p data_sdu_p %p pdu_remaining_size %d\n", rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame, pdu_mem_p, pdu_p, pdu_p->data, data, data_sdu_p,pdu_remaining_size);
|
||||
|
||||
memcpy(data, data_sdu_p, pdu_remaining_size);
|
||||
pdu_mngt_p->payload_size += pdu_remaining_size;
|
||||
sdu_mngt_p->sdu_remaining_size = sdu_mngt_p->sdu_remaining_size - pdu_remaining_size;
|
||||
sdu_mngt_p->sdu_segmented_size = sdu_mngt_p->sdu_segmented_size + pdu_remaining_size;
|
||||
fi_last_byte_pdu_is_last_byte_sdu = 0;
|
||||
// no LI
|
||||
rlc_pP->sdu_buffer_occupancy -= pdu_remaining_size;
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
pdu_remaining_size = 0;
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] sdu_remaining_size %d bytes sdu_segmented_size %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p->sdu_remaining_size,
|
||||
sdu_mngt_p->sdu_segmented_size);
|
||||
} else if (sdu_mngt_p->sdu_remaining_size == pdu_remaining_size) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Exactly Filling remaining PDU with %d remaining bytes of SDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_remaining_size);
|
||||
rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
|
||||
rlc_am_mui.rrc_mui_num++;
|
||||
|
||||
memcpy(data, data_sdu_p, pdu_remaining_size);
|
||||
pdu_mngt_p->payload_size += pdu_remaining_size;
|
||||
|
||||
// free SDU
|
||||
rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
|
||||
rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
|
||||
//free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index], __func__);
|
||||
//rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
|
||||
//rlc_pP->nb_sdu -= 1;
|
||||
rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
|
||||
fi_last_byte_pdu_is_last_byte_sdu = 1;
|
||||
// fi will indicate end of PDU is end of SDU, no need for LI
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
pdu_remaining_size = 0;
|
||||
} else if ((sdu_mngt_p->sdu_remaining_size + (li_length_in_bytes ^ 3)) < pdu_remaining_size ) {
|
||||
if (fill_num_li == (RLC_AM_MAX_SDU_IN_PDU - 1)) {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] [SIZE %d] REACHING RLC_AM_MAX_SDU_IN_PDU LIs -> STOP SEGMENTATION FOR THIS PDU SDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p->sdu_remaining_size);
|
||||
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
|
||||
pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
|
||||
pdu_remaining_size = 0; //Forced to 0 pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
|
||||
// free SDU
|
||||
rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
|
||||
rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
|
||||
//rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
|
||||
//rlc_pP->nb_sdu -= 1;
|
||||
rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
|
||||
// reduce the size of the PDU
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
fi_last_byte_pdu_is_last_byte_sdu = 1;
|
||||
rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
|
||||
rlc_am_mui.rrc_mui_num++;
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling PDU with %d all remaining bytes of SDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p->sdu_remaining_size);
|
||||
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
|
||||
pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
|
||||
data = &data[sdu_mngt_p->sdu_remaining_size];
|
||||
li_length_in_bytes = li_length_in_bytes ^ 3;
|
||||
fill_num_li += 1;
|
||||
|
||||
if (li_length_in_bytes == 2) {
|
||||
if (fill_num_li == test_num_li) {
|
||||
//e_li_p->e1 = 0;
|
||||
e_li_p->b1 = 0;
|
||||
} else {
|
||||
//e_li_p->e1 = 1;
|
||||
e_li_p->b1 = 0x80;
|
||||
}
|
||||
|
||||
//e_li_p->li1 = sdu_mngt_p->sdu_remaining_size;
|
||||
e_li_p->b1 = e_li_p->b1 | (sdu_mngt_p->sdu_remaining_size >> 4);
|
||||
e_li_p->b2 = sdu_mngt_p->sdu_remaining_size << 4;
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] set e_li_p->b1=0x%02X set e_li_p->b2=0x%02X fill_num_li=%d test_num_li=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
e_li_p->b1,
|
||||
e_li_p->b2,
|
||||
fill_num_li,
|
||||
test_num_li);
|
||||
} else {
|
||||
if (fill_num_li != test_num_li) {
|
||||
//e_li_p->e2 = 1;
|
||||
e_li_p->b2 = e_li_p->b2 | 0x08;
|
||||
}
|
||||
|
||||
//e_li_p->li2 = sdu_mngt_p->sdu_remaining_size;
|
||||
e_li_p->b2 = e_li_p->b2 | (sdu_mngt_p->sdu_remaining_size >> 8);
|
||||
e_li_p->b3 = sdu_mngt_p->sdu_remaining_size & 0xFF;
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] set e_li_p->b2=0x%02X set e_li_p->b3=0x%02X fill_num_li=%d test_num_li=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
e_li_p->b2,
|
||||
e_li_p->b3,
|
||||
fill_num_li,
|
||||
test_num_li);
|
||||
e_li_p++;
|
||||
}
|
||||
|
||||
pdu_remaining_size = pdu_remaining_size - (sdu_mngt_p->sdu_remaining_size + li_length_in_bytes);
|
||||
// free SDU
|
||||
rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
|
||||
sdu_mngt_p->sdu_remaining_size = 0;
|
||||
|
||||
rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
|
||||
//free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index], __func__);
|
||||
//rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
|
||||
//rlc_pP->nb_sdu -= 1;
|
||||
rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] Filling PDU with %d all remaining bytes of SDU and reduce TB size by %d bytes\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_mngt_p->sdu_remaining_size,
|
||||
pdu_remaining_size - sdu_mngt_p->sdu_remaining_size);
|
||||
//assert(1!=1);
|
||||
rlc_am_mui.rrc_mui[rlc_am_mui.rrc_mui_num] = sdu_mngt_p->mui;
|
||||
rlc_am_mui.rrc_mui_num++;
|
||||
|
||||
memcpy(data, data_sdu_p, sdu_mngt_p->sdu_remaining_size);
|
||||
pdu_mngt_p->payload_size += sdu_mngt_p->sdu_remaining_size;
|
||||
pdu_remaining_size = pdu_remaining_size - sdu_mngt_p->sdu_remaining_size;
|
||||
// free SDU
|
||||
rlc_pP->sdu_buffer_occupancy -= sdu_mngt_p->sdu_remaining_size;
|
||||
rlc_am_free_in_sdu_data(ctxt_pP, rlc_pP, rlc_pP->current_sdu_index);
|
||||
//rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
|
||||
//rlc_pP->nb_sdu -= 1;
|
||||
rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
|
||||
|
||||
// reduce the size of the PDU
|
||||
continue_fill_pdu_with_sdu = 0;
|
||||
fi_last_byte_pdu_is_last_byte_sdu = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// set framing info
|
||||
if (fi_first_byte_pdu_is_first_byte_sdu) {
|
||||
fi = 0;
|
||||
} else {
|
||||
fi = 2;
|
||||
}
|
||||
|
||||
if (!fi_last_byte_pdu_is_last_byte_sdu) {
|
||||
fi = fi + 1;
|
||||
}
|
||||
|
||||
pdu_p->b1 = pdu_p->b1 | (fi << RLC_AM_PDU_FI_OFFSET);
|
||||
|
||||
// set fist e bit
|
||||
if (fill_num_li > 0) {
|
||||
RLC_AM_PDU_SET_E(pdu_p->b1);
|
||||
}
|
||||
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] SEND PDU SN %04d SIZE %d BYTES PAYLOAD SIZE %d BYTES\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vt_s,
|
||||
data_pdu_size - pdu_remaining_size,
|
||||
pdu_mngt_p->payload_size);
|
||||
|
||||
rlc_pP->stat_tx_data_pdu += 1;
|
||||
rlc_pP->stat_tx_data_bytes += (data_pdu_size - pdu_remaining_size);
|
||||
|
||||
// set DATA/CONTROL field is DATA PDU(1)
|
||||
RLC_AM_PDU_SET_D_C(pdu_p->b1);
|
||||
// set sn = rlc_pP->vt_s;
|
||||
pdu_p->b1 = pdu_p->b1 | (rlc_pP->vt_s >> 8);
|
||||
pdu_p->b2 = rlc_pP->vt_s & 0xFF;
|
||||
rlc_pP->vt_s = (rlc_pP->vt_s+1) & RLC_AM_SN_MASK;
|
||||
|
||||
pdu_tb_req_p->data_ptr = (unsigned char*)pdu_p;
|
||||
pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size;
|
||||
//#warning "why 3000: changed to RLC_SDU_MAX_SIZE "
|
||||
//assert(pdu_tb_req_p->tb_size < RLC_SDU_MAX_SIZE );
|
||||
if(pdu_tb_req_p->tb_size >= RLC_SDU_MAX_SIZE) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] tb_size error. %d, %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),pdu_tb_req_p->tb_size, RLC_SDU_MAX_SIZE);
|
||||
}
|
||||
rlc_am_pdu_polling(ctxt_pP, rlc_pP, pdu_p, pdu_mngt_p->payload_size,true);
|
||||
|
||||
//list_add_tail_eurecom (pdu_mem_p, &rlc_pP->segmentation_pdu_list);
|
||||
pdu_mngt_p->mem_block = pdu_mem_p;
|
||||
pdu_mngt_p->first_byte = (unsigned char*)pdu_p;
|
||||
pdu_mngt_p->header_and_payload_size = data_pdu_size - pdu_remaining_size;
|
||||
pdu_mngt_p->retx_count = 0;
|
||||
pdu_mngt_p->retx_count_next = 0;
|
||||
pdu_mngt_p->flags.retransmit = 0;
|
||||
pdu_mngt_p->flags.transmitted = 1;
|
||||
pdu_mngt_p->sn = RLC_AM_PREV_SN(rlc_pP->vt_s);
|
||||
|
||||
|
||||
//TBC: What for resetting local pointers at the end ??
|
||||
pdu_p = NULL;
|
||||
pdu_mem_p = NULL;
|
||||
|
||||
//nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
|
||||
nb_bytes_to_transmit = 0; // 1 PDU only
|
||||
|
||||
/* We need to copy the PDU to pass to MAC in order to keep it in the buffer for potential retransmissions */
|
||||
mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, RLC_AM_PREV_SN(rlc_pP->vt_s));
|
||||
list_add_tail_eurecom (copy, &rlc_pP->segmentation_pdu_list);
|
||||
|
||||
}
|
||||
|
||||
RLC_AM_MUTEX_UNLOCK(&rlc_pP->lock_input_sdus);
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_segment.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the segmentation of PDCP SDUs.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_internal_segment_impl_ RLC AM Segmentation Internal Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_AM_SEGMENT_H__
|
||||
# define __RLC_AM_SEGMENT_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP, bool is_new_pdu)
|
||||
* \brief Set or not the poll bit in the PDU header depending on RLC AM protocol variables.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] pduP Pointer on the header of the PDU in order to be able to set the poll bit if necessary.
|
||||
* \param[in] payload_sizeP Size of the payload of the PDU.
|
||||
*/
|
||||
void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP, bool is_new_pdu);
|
||||
|
||||
/*! \fn void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP)
|
||||
* \brief Segment a PDU with 10 bits sequence number, based on segmentation information given by MAC (size to transmit).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *const rlcP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* This file is empty. Might be deleted ? */
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_segments_holes.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the re-segmentation of RLC PDUs stored in the retransmission buffer,.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_segment_holes_impl_ RLC AM Resegmentation Implementation
|
||||
* @ingroup _rlc_am_internal_segment_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_SEGMENT_HOLES_H__
|
||||
# define __RLC_AM_SEGMENT_HOLES_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn void rlc_am_clear_holes (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP, rlc_sn_t snP)
|
||||
* \brief Remove all marked holes for PDU with sequence number "snP".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
*/
|
||||
void rlc_am_clear_holes (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn void rlc_am_remove_hole (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP, rlc_sn_t snP, sdu_size_t so_startP, sdu_size_t so_stopP)
|
||||
* \brief Remove for PDU with sequence number "snP" a NACK for byte segment offset [so_startP, so_stopP].
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \param[in] so_startP Start of segment offset.
|
||||
* \param[in] so_stopP End of segment offset.
|
||||
*/
|
||||
void rlc_am_remove_hole (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
const sdu_size_t so_startP,
|
||||
const sdu_size_t so_stopP);
|
||||
|
||||
/*! \fn void rlc_am_get_next_hole (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP, rlc_sn_t snP, sdu_size_t* so_startP, sdu_size_t* so_stopP)
|
||||
* \brief Get for PDU with sequence number "snP" the first hole start and stop parameters.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \param[in,out] so_startP Start of segment offset.
|
||||
* \param[in,out] so_stopP End of segment offset.
|
||||
*/
|
||||
void rlc_am_get_next_hole (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
sdu_size_t* const so_startP,
|
||||
sdu_size_t* const so_stopP);
|
||||
|
||||
/*! \fn void rlc_am_add_hole (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP, rlc_sn_t snP, sdu_size_t so_startP, sdu_size_t so_stopP)
|
||||
* \brief Mark for PDU with sequence number "snP" a NACK for byte segment offset [so_startP, so_stopP].
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlcP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \param[in,out] so_startP Start of segment offset.
|
||||
* \param[in,out] so_stopP End of segment offset.
|
||||
*/
|
||||
void rlc_am_add_hole (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlcP,
|
||||
const rlc_sn_t snP,
|
||||
const sdu_size_t so_startP,
|
||||
sdu_size_t so_stopP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,764 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_STATUS_REPORT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "intertask_interface.h"
|
||||
#include "assertions.h"
|
||||
#include "list.h"
|
||||
#include "rlc_am.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint16_t rlc_am_read_bit_field(
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
const signed int bits_to_readP) {
|
||||
uint16_t value = 0;
|
||||
unsigned int bits_read = 0;
|
||||
signed int bits_to_read = bits_to_readP;
|
||||
|
||||
do {
|
||||
// bits read > bits to read
|
||||
if ((8 - *bit_pos_pP) > bits_to_read) {
|
||||
bits_read = 8 - *bit_pos_pP;
|
||||
value = (value << bits_to_read) | ((((uint16_t)(**data_ppP)) & (uint16_t)(0x00FF >> *bit_pos_pP)) >> (bits_read -
|
||||
bits_to_read));
|
||||
*bit_pos_pP = *bit_pos_pP + bits_to_read;
|
||||
return value;
|
||||
// bits read == bits to read
|
||||
} else if ((8 - *bit_pos_pP) == bits_to_read) {
|
||||
value = (value << bits_to_read) | (((uint16_t)(**data_ppP)) & (uint16_t)(0x00FF >> *bit_pos_pP));
|
||||
*bit_pos_pP = 0;
|
||||
*data_ppP = *data_ppP + 1;
|
||||
return value;
|
||||
// bits read < bits to read
|
||||
} else {
|
||||
bits_read = 8 - *bit_pos_pP;
|
||||
value = (value << bits_read) | ((((uint16_t)(**data_ppP)) & (uint16_t)(0x00FF >> *bit_pos_pP)));
|
||||
*bit_pos_pP = 0;
|
||||
*data_ppP = *data_ppP + 1;
|
||||
bits_to_read = bits_to_read - bits_read;
|
||||
}
|
||||
} while (bits_to_read > 0);
|
||||
|
||||
return value;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_write8_bit_field(
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
const signed int bits_to_writeP,
|
||||
const uint8_t valueP) {
|
||||
unsigned int available_bits;
|
||||
signed int bits_to_write= bits_to_writeP;
|
||||
|
||||
do {
|
||||
available_bits = 8 - *bit_pos_pP;
|
||||
|
||||
// available_bits > bits to write
|
||||
if (available_bits > bits_to_write) {
|
||||
**data_ppP = **data_ppP | (((valueP & (((uint8_t)0xFF) >> (available_bits - bits_to_write)))) << (available_bits -
|
||||
bits_to_write));
|
||||
*bit_pos_pP = *bit_pos_pP + bits_to_write;
|
||||
return;
|
||||
// bits read == bits to read
|
||||
} else if (available_bits == bits_to_write) {
|
||||
**data_ppP = **data_ppP | (valueP & (((uint8_t)0xFF) >> (8 - bits_to_write)));
|
||||
*bit_pos_pP = 0;
|
||||
*data_ppP = *data_ppP + 1;
|
||||
return;
|
||||
// available_bits < bits to write
|
||||
} else {
|
||||
**data_ppP = **data_ppP | (valueP >> (bits_to_write - available_bits));
|
||||
*bit_pos_pP = 0;
|
||||
*data_ppP = *data_ppP + 1;
|
||||
bits_to_write = bits_to_write - available_bits;
|
||||
}
|
||||
} while (bits_to_write > 0);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_write16_bit_field(
|
||||
uint8_t **data_ppP,
|
||||
unsigned int *bit_pos_pP,
|
||||
signed int bits_to_writeP,
|
||||
const uint16_t valueP) {
|
||||
//assert(bits_to_writeP <= 16);
|
||||
if(bits_to_writeP > 16) {
|
||||
LOG_E(RLC, "bits_to_writeP error. %d\n", bits_to_writeP);
|
||||
}
|
||||
|
||||
if (bits_to_writeP > 8) {
|
||||
rlc_am_write8_bit_field(data_ppP,bit_pos_pP, bits_to_writeP - 8, (uint8_t)(valueP >> 8));
|
||||
rlc_am_write8_bit_field(data_ppP,bit_pos_pP, 8, (uint8_t)(valueP & 0x00FF));
|
||||
} else {
|
||||
rlc_am_write8_bit_field(data_ppP,bit_pos_pP, bits_to_writeP, (uint8_t)(valueP & 0x00FF));
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_get_control_pdu_infos(
|
||||
rlc_am_pdu_sn_10_t *const header_pP,
|
||||
sdu_size_t *const total_size_pP,
|
||||
rlc_am_control_pdu_info_t *const pdu_info_pP) {
|
||||
memset(pdu_info_pP, 0, sizeof (rlc_am_control_pdu_info_t));
|
||||
pdu_info_pP->d_c = header_pP->b1 >> 7;
|
||||
|
||||
if (!pdu_info_pP->d_c) {
|
||||
pdu_info_pP->cpt = (header_pP->b1 >> 4) & 0x07;
|
||||
|
||||
if (pdu_info_pP->cpt != 0x00) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
pdu_info_pP->ack_sn = ((header_pP->b2 >> 2) & 0x3F) | (((uint16_t)(header_pP->b1 & 0x0F)) << 6);
|
||||
pdu_info_pP->e1 = (header_pP->b2 >> 1) & 0x01;
|
||||
//*total_size_pP -= 1;
|
||||
|
||||
if (pdu_info_pP->e1) {
|
||||
unsigned int nack_to_read = 1;
|
||||
unsigned int bit_pos = 7; // range from 0 (MSB/left) to 7 (LSB/right)
|
||||
uint8_t *byte_pos_p = &header_pP->b2;
|
||||
|
||||
while (nack_to_read) {
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].nack_sn = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 10);
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].e1 = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 1);
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].e2 = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 1);
|
||||
|
||||
// READ SOstart, SOend field
|
||||
if (pdu_info_pP->nack_list[pdu_info_pP->num_nack].e2) {
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].so_start = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 15);
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].so_end = rlc_am_read_bit_field(&byte_pos_p, &bit_pos, 15);
|
||||
} else {
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].so_start = 0;
|
||||
// all 15 bits set to 1 (indicate that the missing portion of the AMD PDU includes all bytes
|
||||
// to the last byte of the AMD PDU)
|
||||
pdu_info_pP->nack_list[pdu_info_pP->num_nack].so_end = 0x7FFF;
|
||||
}
|
||||
|
||||
pdu_info_pP->num_nack = pdu_info_pP->num_nack + 1;
|
||||
|
||||
if (!pdu_info_pP->nack_list[pdu_info_pP->num_nack - 1].e1) {
|
||||
nack_to_read = 0;
|
||||
*total_size_pP = *total_size_pP - (sdu_size_t)((uint64_t)byte_pos_p + (uint64_t)((bit_pos + 7)/8) - (uint64_t)header_pP);
|
||||
|
||||
if (*total_size_pP != 0) {
|
||||
LOG_E(RLC, "[RLC_AM_GET_CONTROL_PDU_INFOS][FIRST]header_pP->b1=%d,header_pP->b2=%d\n",header_pP->b1,header_pP->b2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdu_info_pP->num_nack == RLC_AM_MAX_NACK_IN_STATUS_PDU) {
|
||||
*total_size_pP = *total_size_pP - (sdu_size_t)((uint64_t)byte_pos_p + (uint64_t)((bit_pos + 7)/8) - (uint64_t)header_pP);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
*total_size_pP = *total_size_pP - (sdu_size_t)((uint64_t)byte_pos_p + (uint64_t)((bit_pos + 7)/8) - (uint64_t)header_pP);
|
||||
} else {
|
||||
*total_size_pP = *total_size_pP - 2;
|
||||
}
|
||||
|
||||
if (*total_size_pP != 0) {
|
||||
LOG_E(RLC, "[RLC_AM_GET_CONTROL_PDU_INFOS][SECOND]header_pP->b1=%d,header_pP->b2=%d\n",header_pP->b1,header_pP->b2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_display_control_pdu_infos(
|
||||
const rlc_am_control_pdu_info_t *const pdu_info_pP
|
||||
) {
|
||||
int num_nack;
|
||||
|
||||
if (!pdu_info_pP->d_c) {
|
||||
LOG_T(RLC, "CONTROL PDU ACK SN %04d", pdu_info_pP->ack_sn);
|
||||
|
||||
for (num_nack = 0; num_nack < pdu_info_pP->num_nack; num_nack++) {
|
||||
if (pdu_info_pP->nack_list[num_nack].e2) {
|
||||
LOG_T(RLC, "\n\tNACK SN %04d SO START %05d SO END %05d", pdu_info_pP->nack_list[num_nack].nack_sn,
|
||||
pdu_info_pP->nack_list[num_nack].so_start,
|
||||
pdu_info_pP->nack_list[num_nack].so_end);
|
||||
} else {
|
||||
LOG_T(RLC, "\n\tNACK SN %04d", pdu_info_pP->nack_list[num_nack].nack_sn);
|
||||
}
|
||||
}
|
||||
|
||||
LOG_T(RLC, "\n");
|
||||
} else {
|
||||
LOG_E(RLC, "CAN'T DISPLAY CONTROL INFO: PDU IS DATA PDU\n");
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_receive_process_control_pdu(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
mem_block_t *const tb_pP,
|
||||
uint8_t **first_byte_ppP,
|
||||
sdu_size_t *const tb_size_in_bytes_pP) {
|
||||
rlc_am_pdu_sn_10_t *rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t *)*first_byte_ppP;
|
||||
sdu_size_t initial_pdu_size = *tb_size_in_bytes_pP;
|
||||
rlc_sn_t ack_sn = RLC_AM_NEXT_SN(rlc_pP->vt_a);
|
||||
rlc_sn_t sn_cursor = rlc_pP->vt_a;
|
||||
rlc_sn_t vt_a_new = rlc_pP->vt_a;
|
||||
rlc_sn_t sn_data_cnf = (rlc_sn_t) 0;
|
||||
rlc_sn_t nack_sn,prev_nack_sn;
|
||||
sdu_size_t data_cnf_so_stop = 0x7FFF;
|
||||
unsigned int nack_index;
|
||||
bool status = true;
|
||||
|
||||
if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, tb_size_in_bytes_pP, &rlc_pP->control_pdu_info) >= 0) {
|
||||
rlc_am_tx_buffer_display(ctxt_pP, rlc_pP, " TX BUFFER BEFORE PROCESS OF STATUS PDU");
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RX CONTROL PDU VT(A) %04d VT(S) %04d POLL_SN %04d ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vt_a,
|
||||
rlc_pP->vt_s,
|
||||
rlc_pP->poll_sn,
|
||||
rlc_pP->control_pdu_info.ack_sn);
|
||||
rlc_am_display_control_pdu_infos(&rlc_pP->control_pdu_info);
|
||||
ack_sn = rlc_pP->control_pdu_info.ack_sn;
|
||||
// 5.2.1 Retransmission
|
||||
//
|
||||
// The transmitting side of an AM RLC entity can receive a negative acknowledgement (notification of reception failure
|
||||
// by its peer AM RLC entity) for an AMD PDU or a portion of an AMD PDU by the following:
|
||||
// - STATUS PDU from its peer AM RLC entity.
|
||||
//
|
||||
// When receiving a negative acknowledgement for an AMD PDU or a portion of an AMD PDU by a STATUS PDU from
|
||||
// its peer AM RLC entity, the transmitting side of the AM RLC entity shall:
|
||||
// - if the SN of the corresponding AMD PDU falls within the range VT(A) <= SN < VT(S):
|
||||
// - consider the AMD PDU or the portion of the AMD PDU for which a negative acknowledgement was
|
||||
// received for retransmission.
|
||||
|
||||
// 5.2.2.2 Reception of a STATUS report
|
||||
// Upon reception of a STATUS report from the receiving RLC AM entity the
|
||||
// transmitting side of an AM RLC entity shall:
|
||||
// - if the STATUS report comprises a positive or negative
|
||||
// acknowledgement for the RLC data PDU with sequence number equal to
|
||||
// POLL_SN:
|
||||
// - if t-PollRetransmit is running:
|
||||
// - stop and reset t-PollRetransmit.
|
||||
//assert(ack_sn < RLC_AM_SN_MODULO);
|
||||
//assert(rlc_pP->control_pdu_info.num_nack < RLC_AM_MAX_NACK_IN_STATUS_PDU);
|
||||
if(ack_sn >= RLC_AM_SN_MODULO || rlc_pP->control_pdu_info.num_nack >= RLC_AM_MAX_NACK_IN_STATUS_PDU) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" illegal ack_sn %d, num_nack %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), ack_sn, rlc_pP->control_pdu_info.num_nack);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note : ackSn can be equal to current vtA only in case the status pdu contains a list of nack_sn with same value = vtA with SOStart/SOEnd */
|
||||
/* and meaning the report is not complete due to not enough ressources to fill all SOStart/SOEnd of this NACK_SN */
|
||||
if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a)) {
|
||||
if (rlc_pP->control_pdu_info.num_nack == 0) {
|
||||
while (sn_cursor != ack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor, true);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
vt_a_new = ack_sn;
|
||||
sn_data_cnf = RLC_AM_PREV_SN(vt_a_new);
|
||||
} else {
|
||||
nack_index = 0;
|
||||
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
|
||||
prev_nack_sn = 0x3FFF;
|
||||
|
||||
while (sn_cursor != nack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor, true);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
vt_a_new = nack_sn;
|
||||
// catch DataCfn
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[nack_sn % RLC_AM_WINDOW_SIZE];
|
||||
|
||||
if (tx_data_pdu_buffer_p->retx_payload_size == tx_data_pdu_buffer_p->payload_size) {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
} else if (tx_data_pdu_buffer_p->nack_so_start != 0) {
|
||||
sn_data_cnf = nack_sn;
|
||||
data_cnf_so_stop = tx_data_pdu_buffer_p->nack_so_start - 1;
|
||||
} else {
|
||||
sn_data_cnf = RLC_AM_PREV_SN(nack_sn);
|
||||
}
|
||||
|
||||
while ((sn_cursor != ack_sn) && (status)) {
|
||||
if (sn_cursor != nack_sn) {
|
||||
rlc_am_ack_pdu(ctxt_pP,
|
||||
rlc_pP,
|
||||
sn_cursor,
|
||||
false);
|
||||
} else {
|
||||
status = rlc_am_nack_pdu (ctxt_pP,
|
||||
rlc_pP,
|
||||
nack_sn,
|
||||
prev_nack_sn,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_start,
|
||||
rlc_pP->control_pdu_info.nack_list[nack_index].so_end);
|
||||
nack_index = nack_index + 1;
|
||||
prev_nack_sn = nack_sn;
|
||||
|
||||
if (nack_index < rlc_pP->control_pdu_info.num_nack) {
|
||||
nack_sn = rlc_pP->control_pdu_info.nack_list[nack_index].nack_sn;
|
||||
} else if (nack_sn != ack_sn) {
|
||||
/* general case*/
|
||||
nack_sn = ack_sn;
|
||||
} else {
|
||||
/*specific case when the sender did not have enough TBS to fill all SOStart SOEnd for this NACK_SN */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_nack_sn != nack_sn) {
|
||||
/* do not increment sn_cursor in case of several informations for the same nack_sn */
|
||||
sn_cursor = (sn_cursor + 1) & RLC_AM_SN_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN %d OUT OF WINDOW vtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,rlc_pP->vt_a,rlc_pP->vt_s);
|
||||
*tb_size_in_bytes_pP = 0;
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR IN DECODING CONTROL PDU\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
*tb_size_in_bytes_pP = 0;
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* Check for Stopping TpollReTx */
|
||||
if ((rlc_pP->poll_sn != RLC_SN_UNDEFINED) &&
|
||||
(RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a) > RLC_AM_DIFF_SN(rlc_pP->poll_sn,rlc_pP->vt_a))) {
|
||||
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP, rlc_pP);
|
||||
rlc_pP->poll_sn = RLC_SN_UNDEFINED;
|
||||
}
|
||||
|
||||
//TODO : this part does not cover all cases of Data Cnf and move it at the end of Status PDU processing
|
||||
sn_cursor = rlc_pP->vt_a;
|
||||
|
||||
// Fix Issue 238 : check sn_data_cnf has been transmitted
|
||||
if ((rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].flags.transmitted) &&
|
||||
(rlc_pP->tx_data_pdu_buffer[sn_data_cnf % RLC_AM_WINDOW_SIZE].sn == sn_data_cnf)) {
|
||||
/* Handle all acked PDU up to and excluding sn_data_cnf */
|
||||
while (sn_cursor != sn_data_cnf) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_cursor);
|
||||
sn_cursor = RLC_AM_NEXT_SN(sn_cursor);
|
||||
}
|
||||
|
||||
// Handle last SN. TO DO : case of PDU partially ACKED with SDU to be data conf
|
||||
if (data_cnf_so_stop == 0x7FFF) {
|
||||
rlc_am_pdu_sdu_data_cnf(ctxt_pP,rlc_pP,sn_data_cnf);
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU ACK_SN=%d NewvtA=%d OldvtA=%d SnDataCnf=%d DataCnfSOStop=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,sn_data_cnf,data_cnf_so_stop,rlc_pP->vt_s);
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" RECEIVE STATUS PDU WITH NO SDU CNF ACK_SN=%d NewvtA=%d OldvtA=%d vtS=%d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,vt_a_new,rlc_pP->vt_a,rlc_pP->vt_s);
|
||||
}
|
||||
|
||||
/* Update vtA and vtMS */
|
||||
rlc_pP->vt_a = vt_a_new;
|
||||
rlc_pP->vt_ms = (rlc_pP->vt_a + RLC_AM_WINDOW_SIZE) & RLC_AM_SN_MASK;
|
||||
}
|
||||
|
||||
*first_byte_ppP = (uint8_t *)((uint64_t)*first_byte_ppP + initial_pdu_size - *tb_size_in_bytes_pP);
|
||||
free_mem_block(tb_pP, __func__);
|
||||
rlc_am_tx_buffer_display(ctxt_pP, rlc_pP, NULL);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_am_write_status_pdu(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t *const rlc_am_pdu_sn_10_pP,
|
||||
rlc_am_control_pdu_info_t *const pdu_info_pP) {
|
||||
unsigned int bit_pos = 4; // range from 0 (MSB/left) to 7 (LSB/right)
|
||||
uint8_t *byte_pos_p = &rlc_am_pdu_sn_10_pP->b1;
|
||||
unsigned int index = 0;
|
||||
unsigned int num_bytes = 0;
|
||||
rlc_am_write16_bit_field(&byte_pos_p, &bit_pos, 10, pdu_info_pP->ack_sn);
|
||||
|
||||
if (pdu_info_pP->num_nack > 0) {
|
||||
rlc_am_write8_bit_field(&byte_pos_p, &bit_pos, 1, 1);
|
||||
} else {
|
||||
rlc_am_write8_bit_field(&byte_pos_p, &bit_pos, 1, 0);
|
||||
}
|
||||
|
||||
for (index = 0; index < pdu_info_pP->num_nack ; index++) {
|
||||
rlc_am_write16_bit_field(&byte_pos_p, &bit_pos, 10, pdu_info_pP->nack_list[index].nack_sn);
|
||||
rlc_am_write8_bit_field(&byte_pos_p, &bit_pos, 1, pdu_info_pP->nack_list[index].e1);
|
||||
rlc_am_write8_bit_field(&byte_pos_p, &bit_pos, 1, pdu_info_pP->nack_list[index].e2);
|
||||
|
||||
// if SO_START SO_END fields
|
||||
if (pdu_info_pP->nack_list[index].e2 > 0) {
|
||||
rlc_am_write16_bit_field(&byte_pos_p, &bit_pos, 15, pdu_info_pP->nack_list[index].so_start);
|
||||
rlc_am_write16_bit_field(&byte_pos_p, &bit_pos, 15, pdu_info_pP->nack_list[index].so_end);
|
||||
}
|
||||
}
|
||||
|
||||
ptrdiff_t diff = byte_pos_p - &rlc_am_pdu_sn_10_pP->b1; // this is the difference in terms of typeof(byte_pos_p), which is uint8_t
|
||||
num_bytes = diff;
|
||||
|
||||
if (bit_pos > 0) {
|
||||
num_bytes += 1;
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WROTE STATUS PDU %d BYTES\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
num_bytes);
|
||||
return num_bytes;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_send_status_pdu(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
) {
|
||||
// When STATUS reporting has been triggered, the receiving side of an AM RLC entity shall:
|
||||
// - if t-StatusProhibit is not running:
|
||||
// - at the first transmission opportunity indicated by lower layer, construct a STATUS PDU and deliver it to lower layer;
|
||||
// - else:
|
||||
// - at the first transmission opportunity indicated by lower layer after t-StatusProhibit expires, construct a single
|
||||
// STATUS PDU even if status reporting was triggered several times while t-StatusProhibit was running and
|
||||
// deliver it to lower layer;
|
||||
//
|
||||
// When a STATUS PDU has been delivered to lower layer, the receiving side of an AM RLC entity shall:
|
||||
// - start t-StatusProhibit.
|
||||
//
|
||||
// When constructing a STATUS PDU, the AM RLC entity shall:
|
||||
// - for the AMD PDUs with SN such that VR(R) <= SN < VR(MR) that has not been completely received yet, in
|
||||
// increasing SN of PDUs and increasing byte segment order within PDUs, starting with SN = VR(R) up to
|
||||
// the point where the resulting STATUS PDU still fits to the total size of RLC PDU(s) indicated by lower layer:
|
||||
// - for an AMD PDU for which no byte segments have been received yet::
|
||||
// - include in the STATUS PDU a NACK_SN which is set to the SN of the AMD PDU;
|
||||
// - for a continuous sequence of byte segments of a partly received AMD PDU that have not been received yet:
|
||||
// - include in the STATUS PDU a set of NACK_SN, SOstart and SOend
|
||||
// - set the ACK_SN to the SN of the next not received RLC Data PDU which is not indicated as missing in the
|
||||
// resulting STATUS PDU.
|
||||
signed int nb_bits_to_transmit = rlc_pP->nb_bytes_requested_by_mac << 3;
|
||||
// minimum header size in bits to be transmitted: D/C + CPT + ACK_SN + E1
|
||||
signed int nb_bits_transmitted = RLC_AM_PDU_D_C_BITS + RLC_AM_STATUS_PDU_CPT_LENGTH + RLC_AM_SN_BITS + RLC_AM_PDU_E_BITS;
|
||||
rlc_am_control_pdu_info_t control_pdu_info;
|
||||
rlc_am_pdu_info_t *pdu_info_cursor_p = NULL;
|
||||
rlc_sn_t sn_cursor = 0;
|
||||
rlc_sn_t sn_nack = rlc_pP->vr_r;
|
||||
mem_block_t *cursor_p = rlc_pP->receiver_buffer.head;
|
||||
int all_segments_received = 0;
|
||||
int waited_so = 0;
|
||||
mem_block_t *tb_p = NULL;
|
||||
sdu_size_t pdu_size = 0;
|
||||
bool status_report_completed = false;
|
||||
bool segment_loop_end = false;
|
||||
memset(&control_pdu_info, 0, sizeof(rlc_am_control_pdu_info_t));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] nb_bits_to_transmit %d (15 already allocated for header)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
nb_bits_to_transmit);
|
||||
rlc_am_rx_list_display(rlc_pP, " DISPLAY BEFORE CONSTRUCTION OF STATUS REPORT");
|
||||
|
||||
/* Handle no NACK first */
|
||||
if (rlc_pP->vr_r == rlc_pP->vr_ms) {
|
||||
control_pdu_info.ack_sn = rlc_pP->vr_ms;
|
||||
status_report_completed = true;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d ALL ACK WITH ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
rlc_pP->vr_ms);
|
||||
} else if ((cursor_p != NULL) && ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1)) <= nb_bits_to_transmit)) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
sn_cursor = pdu_info_cursor_p->sn;
|
||||
/* Set E1 bit for the presence of first NACK_SN/E1/E2 */
|
||||
control_pdu_info.e1 = 1;
|
||||
|
||||
// 12 bits = size of NACK_SN field + E1, E2 bits
|
||||
// 42 bits = size of NACK_SN field + SO_START, SO_END fields, E1, E2 bits
|
||||
while ((!status_report_completed) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))
|
||||
&& (cursor_p != NULL) && (nb_bits_transmitted <= nb_bits_to_transmit)) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
sn_cursor = pdu_info_cursor_p->sn;
|
||||
all_segments_received = ((rlc_am_rx_pdu_management_t *)(cursor_p->data))->all_segments_received;
|
||||
|
||||
/* First fill NACK_SN with each missing PDU between current sn_nack and sn_cursor */
|
||||
while ((sn_nack != sn_cursor) && (RLC_AM_DIFF_SN(sn_nack,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r))) {
|
||||
if (nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) <= nb_bits_to_transmit) {
|
||||
/* Fill NACK_SN infos */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_nack;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 0;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_nack);
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_nack);
|
||||
} else {
|
||||
/* Not enough UL TBS*/
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d NOT ENOUGH TBS STOP WITH ACK_SN %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_nack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sn_nack == rlc_pP->vr_ms) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now process all Segments of sn_cursor if PDU not fully received */
|
||||
if ((!status_report_completed) && (all_segments_received == 0) && (sn_cursor != rlc_pP->vr_ms)) {
|
||||
//AssertFatal (sn_nack == sn_cursor, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
if(sn_nack != sn_cursor) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data sn_nack=%d and sn_cursor=%d should be equal LcId=%d\n",sn_nack,sn_cursor, rlc_pP->channel_id);
|
||||
}
|
||||
/* First ensure there is enough TBS for at least 1 SOStart/SOEnd, else break */
|
||||
else if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
/* Init loop flags */
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
/* Init first SO Start according to first segment */
|
||||
if (pdu_info_cursor_p->so) {
|
||||
/* Fill the first SO */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = 0;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
0,
|
||||
pdu_info_cursor_p->so - 1);
|
||||
waited_so = pdu_info_cursor_p->so + pdu_info_cursor_p->payload_size;
|
||||
} else {
|
||||
waited_so = pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
|
||||
/* Find the first discontinuity and then fill SOStart/SOEnd */
|
||||
while (!segment_loop_end) {
|
||||
if ((cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)) {
|
||||
/* PDU segment is for the same SN*/
|
||||
/* Check lsf */
|
||||
segment_loop_end = (pdu_info_cursor_p->lsf == 1);
|
||||
|
||||
if (waited_so < pdu_info_cursor_p->so) {
|
||||
/* SO is greater than previous received portion : gap identified to fill */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = pdu_info_cursor_p->so - 1;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
pdu_info_cursor_p->so);
|
||||
} else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
segment_loop_end = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* contiguous segment: only update waited_so */
|
||||
/* Assuming so and payload_size updated according to duplication removal done at reception ... */
|
||||
waited_so += pdu_info_cursor_p->payload_size;
|
||||
}
|
||||
|
||||
/* Go to next received PDU or PDU Segment */
|
||||
cursor_p = cursor_p->next;
|
||||
|
||||
if (cursor_p != NULL) {
|
||||
pdu_info_cursor_p = &((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info;
|
||||
}
|
||||
} //end if (cursor_p != NULL) && (pdu_info_cursor_p->sn == sn_cursor)
|
||||
else {
|
||||
/* Previous PDU segment was the last one and did not have lsf indication : fill the latest gap */
|
||||
if ((nb_bits_transmitted + RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1)) <= nb_bits_to_transmit) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].nack_sn = sn_cursor;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_start = waited_so;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].so_end = RLC_AM_STATUS_PDU_SO_END_ALL_BYTES;
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e2 = 1;
|
||||
/* Set E1 for next NACK_SN. The last one will be cleared */
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack].e1 = 1;
|
||||
control_pdu_info.num_nack += 1;
|
||||
nb_bits_transmitted += (RLC_AM_SN_BITS + (RLC_AM_PDU_E_BITS << 1) + (RLC_AM_STATUS_PDU_SO_LENGTH << 1));
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING LAST NACK %04d SO START %05d SO END %05d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
sn_cursor,
|
||||
waited_so,
|
||||
RLC_AM_STATUS_PDU_SO_END_ALL_BYTES);
|
||||
} else {
|
||||
/* Not enough resources to set a SOStart/SEnd, then set ACK_SN to current NACK_SN and stop Status PDU build */
|
||||
control_pdu_info.ack_sn = sn_cursor;
|
||||
status_report_completed = true;
|
||||
}
|
||||
|
||||
segment_loop_end = true;
|
||||
}
|
||||
} //end while (!segment_loop_end)
|
||||
} // end if enough resource for transmitting at least one SOStart/SOEnd
|
||||
else {
|
||||
/* Not enough UL TBS to set at least one SOStart/SOEnd */
|
||||
/* latest value of sn_nack shall be used as ACK_SN */
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
status_report_completed = true;
|
||||
}
|
||||
} // end while on all PDU segments of sn_cursor
|
||||
else {
|
||||
/* Go to next received PDU or PDU segment with different SN */
|
||||
do {
|
||||
cursor_p = cursor_p->next;
|
||||
} while ((cursor_p != NULL) && (((rlc_am_rx_pdu_management_t *)(cursor_p->data))->pdu_info.sn == sn_cursor));
|
||||
}
|
||||
|
||||
/* Increment sn_nack except if sn_cursor = vrMS and if current SN was not fully received */
|
||||
if (RLC_AM_DIFF_SN(sn_cursor,rlc_pP->vr_r) < RLC_AM_DIFF_SN(rlc_pP->vr_ms,rlc_pP->vr_r)) {
|
||||
sn_nack = RLC_AM_NEXT_SN(sn_cursor);
|
||||
} else {
|
||||
sn_nack = rlc_pP->vr_ms;
|
||||
}
|
||||
} // End main while NACK_SN
|
||||
|
||||
/* Clear E1 of last nack_sn entry */
|
||||
// AssertFatal ((control_pdu_info.num_nack) || (all_segments_received == 0), "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
// rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
if (!((control_pdu_info.num_nack) || (all_segments_received == 0))) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data Error no NACK_SN vrR=%d vrMS=%d lastSN_NACK=%d Completed=%d NbBytesAvailable=%d LcId=%d\n",
|
||||
rlc_pP->vr_r,rlc_pP->vr_ms,sn_nack,status_report_completed,(nb_bits_to_transmit >> 3),rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (control_pdu_info.num_nack) {
|
||||
control_pdu_info.nack_list[control_pdu_info.num_nack - 1].e1 = 0;
|
||||
}
|
||||
|
||||
/* Set ACK_SN unless it was set before */
|
||||
if (!status_report_completed) {
|
||||
control_pdu_info.ack_sn = sn_nack;
|
||||
}
|
||||
} else {
|
||||
/* reception buffer empty or not enough TBS for filling at least 1 NACK_SN + E1 + E2 */
|
||||
control_pdu_info.ack_sn = rlc_pP->vr_r;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d = VR(R)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
control_pdu_info.ack_sn);
|
||||
}
|
||||
|
||||
//msg ("[FRAME %5u][%s][RLC_AM][MOD %u/%u][RB %u] nb_bits_to_transmit %d\n",
|
||||
// rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame,nb_bits_to_transmit);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d PREPARE SENDING ACK %04d NUM NACK %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
control_pdu_info.ack_sn,
|
||||
control_pdu_info.num_nack);
|
||||
/* encode the control pdu */
|
||||
pdu_size = (nb_bits_transmitted + 7) >> 3;
|
||||
|
||||
// AssertFatal (pdu_size <= rlc_pP->nb_bytes_requested_by_mac, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
// pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
if(pdu_size > rlc_pP->nb_bytes_requested_by_mac) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data size=%d bigger than remaining TBS=%d nb_bits_transmitted=%d LcId=%d\n",
|
||||
pdu_size,rlc_pP->nb_bytes_requested_by_mac,nb_bits_transmitted, rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] LINE %d forecast pdu_size %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
__LINE__,
|
||||
pdu_size);
|
||||
tb_p = get_free_mem_block(sizeof(struct mac_tb_req) + pdu_size, __func__);
|
||||
|
||||
if(tb_p == NULL) return;
|
||||
|
||||
memset(tb_p->data, 0, sizeof(struct mac_tb_req) + pdu_size);
|
||||
//estimation only ((struct mac_tb_req*)(tb_p->data))->tb_size = pdu_size;
|
||||
((struct mac_tb_req *)(tb_p->data))->data_ptr = (uint8_t *)&(tb_p->data[sizeof(struct mac_tb_req)]);
|
||||
// warning reuse of pdu_size
|
||||
// TODO : rlc_am_write_status_pdu should be rewritten as not very tested ...
|
||||
pdu_size = rlc_am_write_status_pdu(ctxt_pP, rlc_pP,(rlc_am_pdu_sn_10_t *)(((struct mac_tb_req *)(tb_p->data))->data_ptr), &control_pdu_info);
|
||||
((struct mac_tb_req *)(tb_p->data))->tb_size = pdu_size;
|
||||
//assert((((struct mac_tb_req*)(tb_p->data))->tb_size) < 3000);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] SEND STATUS PDU SIZE %d, rlc_pP->nb_bytes_requested_by_mac %d, nb_bits_to_transmit>>3 %d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
pdu_size,
|
||||
rlc_pP->nb_bytes_requested_by_mac,
|
||||
nb_bits_to_transmit >> 3);
|
||||
|
||||
// AssertFatal (pdu_size == ((nb_bits_transmitted + 7) >> 3), "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
// pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
if(pdu_size != ((nb_bits_transmitted + 7) >> 3)) {
|
||||
LOG_E(RLC, "RLC AM Tx Status PDU Data encoding size=%d different than expected=%d LcId=%d\n",
|
||||
pdu_size,((nb_bits_transmitted + 7) >> 3), rlc_pP->channel_id);
|
||||
pdu_size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// remaining bytes to transmit for RLC (retrans pdus and new data pdus)
|
||||
rlc_pP->nb_bytes_requested_by_mac = rlc_pP->nb_bytes_requested_by_mac - pdu_size;
|
||||
// put pdu in trans
|
||||
list_add_head(tb_p, &rlc_pP->control_pdu_list);
|
||||
rlc_pP->stat_tx_control_pdu += 1;
|
||||
rlc_pP->stat_tx_control_bytes += pdu_size;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_status_report.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the reading/writting of informations from/in RLC AM control PDUs, and the processing of received control PDUs.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_status_report_impl_ RLC AM Status Report Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_STATUS_REPORT_H__
|
||||
# define __RLC_AM_STATUS_REPORT_H__
|
||||
|
||||
# include "UTIL/MEM/mem_block.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//#include "PHY/defs.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn uint16_t rlc_am_read_bit_field (uint8_t** dataP, unsigned int* bit_posP, const signed int bits_to_readP)
|
||||
* \brief Read N bits in a byte area seen as a bit-field with the help of a byte index and a modulo 8 bit index.
|
||||
* \param[in,out] dataP Data pointer on area to read, updated after the read.
|
||||
* \param[in,out] bit_posP Last ending read bit position, updated after the read.
|
||||
* \param[in] bits_to_readP Number of bits to read (max 16).
|
||||
* \return Value read on 16 bits, bits read are shifted to least significant bits of returned short value.
|
||||
*/
|
||||
uint16_t rlc_am_read_bit_field (uint8_t** dataP, unsigned int* bit_posP, const signed int bits_to_readP);
|
||||
|
||||
/*! \fn void rlc_am_write8_bit_field(uint8_t** dataP, unsigned int* bit_posP, signed int bits_to_writeP, const uint8_t valueP)
|
||||
* \brief Write N bits (max 8) in a byte area seen as a bit-field with the help of a byte index and a modulo 8 bit index.
|
||||
* \param[in,out] dataP Data pointer on area to write, updated after the write.
|
||||
* \param[in,out] bit_posP Last ending read write position, updated after the write.
|
||||
* \param[in] bits_to_writeP Number of bits to write (max 8).
|
||||
* \param[in] valueP Value to write.
|
||||
*/
|
||||
void rlc_am_write8_bit_field(uint8_t** dataP, unsigned int* bit_posP, signed int bits_to_writeP, const uint8_t valueP);
|
||||
|
||||
/*! \fn void rlc_am_write16_bit_field(uint8_t** dataP, unsigned int* bit_posP, signed int bits_to_writeP, const uint16_t valueP)
|
||||
* \brief Write N bits (max 16) in a byte area seen as a bit-field with the help of a byte index and a modulo 8 bit index.
|
||||
* \param[in,out] dataP Data pointer on area to write, updated after the write.
|
||||
* \param[in,out] bit_posP Last ending read write position, updated after the write.
|
||||
* \param[in] bits_to_writeP Number of bits to write (max 16).
|
||||
* \param[in] valueP Value to write.
|
||||
*/
|
||||
void rlc_am_write16_bit_field(
|
||||
uint8_t** dataP,
|
||||
unsigned int* bit_posP,
|
||||
signed int bits_to_writeP,
|
||||
const uint16_t valueP);
|
||||
|
||||
/*! \fn signed int rlc_am_get_control_pdu_infos (rlc_am_pdu_sn_10_t* const headerP, sdu_size_t * const total_sizeP, rlc_am_control_pdu_info_t* const pdu_infoP)
|
||||
* \brief Retrieve control PDU informations from a serialized control PDU.
|
||||
* \param[in] headerP Pointer on the header of the RLC AM PDU.
|
||||
* \param[in] total_size_pP Pointer on PDU size in bytes.
|
||||
* \param[in,out] pdu_infoP Struct containing interpreted PDU control informations.
|
||||
*/
|
||||
signed int rlc_am_get_control_pdu_infos (
|
||||
rlc_am_pdu_sn_10_t* const headerP,
|
||||
sdu_size_t * const total_size_pP,
|
||||
rlc_am_control_pdu_info_t* const pdu_infoP);
|
||||
|
||||
/*! \fn void rlc_am_display_control_pdu_infos(const rlc_am_control_pdu_info_t* const pdu_infoP)
|
||||
* \brief Dump on LOG output the informations contained in the pdu_infoP structure.
|
||||
* \param[in] pdu_infoP Struct containing interpreted PDU control informations.
|
||||
*/
|
||||
void rlc_am_display_control_pdu_infos(const rlc_am_control_pdu_info_t* const pdu_infoP);
|
||||
|
||||
/*! \fn void rlc_am_receive_process_control_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, mem_block_t* const tbP, uint8_t* first_byte, const uint16_t tb_size_in_bytes)
|
||||
* \brief Process the informations contained in the control PDU.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] tbP Control PDU embedded in a mem_block_t structure.
|
||||
* \param[in] first_byte Pointer on first byte of control PDU.
|
||||
* \param[in] tb_size_in_bytes Pointer on size of serialized control PDU in bytes.
|
||||
*/
|
||||
void rlc_am_receive_process_control_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP,
|
||||
mem_block_t* const tbP,
|
||||
uint8_t** first_byte,
|
||||
sdu_size_t * const tb_size_in_bytes);
|
||||
|
||||
/*! \fn int rlc_am_write_status_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, rlc_am_pdu_sn_10_t* const rlc_am_pdu_sn_10P, rlc_am_control_pdu_info_t* const pdu_infoP)
|
||||
* \brief Remove all marked holes for PDU with sequence number "snP".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] rlc_am_pdu_sn_10P Pointer on the header of the RLC AM control PDU.
|
||||
* \param[in] pdu_infoP Struct containing PDU control informations elements.
|
||||
* \return The number of bytes that have been written.
|
||||
*/
|
||||
int rlc_am_write_status_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
rlc_am_pdu_sn_10_t* const rlc_am_pdu_sn_10P,
|
||||
rlc_am_control_pdu_info_t* const pdu_infoP);
|
||||
|
||||
/*! \fn void rlc_am_send_status_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Send a status PDU based on the receiver buffer content.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_send_status_pdu(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,302 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_structs.h
|
||||
* \brief This file defines structures used inside the RLC AM.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
# ifndef __RLC_AM_STRUCTS_H__
|
||||
# define __RLC_AM_STRUCTS_H__
|
||||
|
||||
# include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
# include "list.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_am_constants.h"
|
||||
# include "mac_rlc_primitives.h"
|
||||
# include "mac_primitives.h"
|
||||
# include "rlc_primitives.h"
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_input_sdu_impl_
|
||||
* @{
|
||||
*/
|
||||
//-----------------------------------------------------------------------------
|
||||
// SDU MANAGEMENT
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \struct sdu_management_flags_t
|
||||
* \brief Structure containing SDU bit-field flags (for memory optimization purpose) related to its segmentation and transmission.
|
||||
*/
|
||||
typedef struct sdu_management_flags {
|
||||
uint8_t discarded:1; /*!< \brief Boolean telling if this SDU is discarded, actually unused. */
|
||||
uint8_t segmented:1; /*!< \brief Boolean telling if the segmentation of this SDU is completed, actually unused. */
|
||||
uint8_t segmentation_in_progress:1; /*!< \brief Boolean telling if the segmentation of this SDU is started but not completed, actually unused. */
|
||||
uint8_t no_new_sdu_segmented_in_last_pdu:1; /*!< \brief Actually unused. */
|
||||
uint8_t transmitted_successfully:1; /*!< \brief SDU acknowledged by peer RLC AM. */
|
||||
uint8_t dummy:3; /*!< \brief Free bits. */
|
||||
} sdu_management_flags_t;
|
||||
|
||||
/*! \struct rlc_am_tx_sdu_management_t
|
||||
* \brief Structure containing SDU variables related to its segmentation and transmission.
|
||||
*/
|
||||
typedef struct rlc_am_tx_sdu_management {
|
||||
mem_block_t *mem_block; /*!< \brief SDU embedded in a mem_block_t. */
|
||||
uint8_t *first_byte; /*!< \brief Pointer on SDU payload. */
|
||||
frame_t sdu_creation_time; /*!< \brief Time stamped with mac_xface->frame. */
|
||||
mui_t mui; /*!< \brief Message Unit Identifier, still here for historical reasons (no LTE-PDCP compliant now). */
|
||||
sdu_size_t sdu_remaining_size; /*!< \brief Remaining size in bytes to be filled in a PDU. */
|
||||
sdu_size_t sdu_segmented_size; /*!< \brief Bytes already segmented in a/several PDU(s). */
|
||||
sdu_size_t sdu_size; /*!< \brief SDU size in bytes. */
|
||||
int16_t pdus_index[RLC_AM_MAX_SDU_FRAGMENTS]; /*!< \brief Array containing the sequence numbers of the PDU in which the SDU has been segmented. */
|
||||
uint8_t nb_pdus; /*!< \brief Number of referenced PDUs in pdus_index[] array. */
|
||||
uint8_t nb_pdus_ack; /*!< \brief Number of referenced PDUs in pdus_index[] array that have been acknowledged. (used for confirmation and MaxDat discard)*/
|
||||
sdu_management_flags_t flags; /*!< \brief bit-field flags related to SDU segmentation and transmission */
|
||||
} rlc_am_tx_sdu_management_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_retransmit_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! \struct pdu_management_flags_t
|
||||
* \brief Structure containing PDU variables related to its retransmission.
|
||||
*/
|
||||
typedef struct pdu_management_flags {
|
||||
uint8_t transmitted:1; /*!< \brief Boolean telling that this PDU is not empty and has been at least transmitted once. */
|
||||
uint8_t ack:1; /*!< \brief Boolean telling that this PDU has been acknowledged. */
|
||||
uint8_t nack:1; /*!< \brief Boolean telling that this PDU has been acknowledged negatively. */
|
||||
uint8_t retransmit:1; /*!< \brief Boolean telling a retransmission is scheduled for this PDU. */
|
||||
uint8_t max_retransmit:1; /*!< \brief Boolean telling max retransmission has been hit for this PDU. */
|
||||
uint8_t dummy:3; /*!< \brief Free bits. */
|
||||
} pdu_management_flags_t;
|
||||
|
||||
|
||||
|
||||
/*! \struct rlc_am_tx_data_pdu_management_t
|
||||
* \brief Structure containing PDU variables related to its acknowlegment, non acknowlegment, resegmentation and retransmission.
|
||||
*/
|
||||
typedef struct rlc_am_tx_data_pdu_management {
|
||||
mem_block_t *mem_block; /*!< \brief PDU embedded in a mem_block_t struct */
|
||||
uint8_t *first_byte; /*!< \brief Pointer on the PDU including header, LIs, data */
|
||||
uint8_t *payload; /*!< \brief Pointer on the PDU payload */
|
||||
int16_t sdus_index[RLC_AM_MAX_SDU_IN_PDU]; /*!< \brief Index of SDU(s) having segments in this pdu (index in rlc_am_entity.input_sdus[]) */
|
||||
frame_t last_nack_time; /*!< \brief Last frame this PDU was negative acknowledged, for not nacking several times in the same frame */
|
||||
sdu_size_t hole_so_start [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the start segment offsets for marking a hole (negative acknowledged area) in the PDU. */
|
||||
sdu_size_t hole_so_stop [RLC_AM_MAX_HOLES_REPORT_PER_PDU]; /*!< \brief Array containing the stop segment offsets for marking a hole (negative acknowledged area) in the PDU. */
|
||||
uint8_t num_holes; /*!< \brief Number of registereg holes in hole_so_start[], hole_so_stop[]. */
|
||||
uint8_t retx_hole_index; /*!< \brief Next index of registered holes to retransmit. */
|
||||
sdu_size_t header_and_payload_size; /*!< \brief Size of the PDU in bytes, including header and payload. */
|
||||
sdu_size_t payload_size; /*!< \brief Size of the PDU payload in bytes. */
|
||||
sdu_size_t retx_payload_size; /*!< \brief Size of the PDU payload to be retransmitted in bytes including all Segment portions. */
|
||||
rlc_sn_t sn; /*!< \brief Sequence number of the PDU. */
|
||||
sdu_size_t nack_so_start; /*!< \brief Lowest NACK start segment offset, must be set to 0 if global NACK. */
|
||||
sdu_size_t nack_so_stop; /*!< \brief Highest NACK stop segment offset, must be set to data_size - 1 if global NACK */
|
||||
|
||||
int8_t nb_sdus; /*!< \brief Number of sdu having segments in this pdu. */
|
||||
int8_t retx_count; /*!< \brief Counts the number of already occurred retransmissions of an AMD PDU (see subclause 5.2.1). */
|
||||
int8_t retx_count_next; /*!< \brief Counts the number of already occurred retransmissions plus the latest pending one. */
|
||||
|
||||
pdu_management_flags_t flags; /*!< \brief PDU variables related to its retransmission. */
|
||||
} rlc_am_tx_data_pdu_management_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @addtogroup _rlc_am_status_report_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! \struct nack_sn_t
|
||||
* \brief Structure containing Status PDU information element.
|
||||
*/
|
||||
typedef struct nack_sn {
|
||||
uint16_t nack_sn:10; /*!< \brief NACK sequence number field. */
|
||||
uint16_t e1:1; /*!< \brief Extension bit 1 field. */
|
||||
uint16_t e2:1; /*!< \brief Extension bit 2 field. */
|
||||
uint32_t so_start:15; /*!< \brief Optional SOstart field (depending on e2 bit). */
|
||||
uint32_t so_end:15; /*!< \brief Optional SOend field (depending on e2 bit). */
|
||||
} nack_sn_t;
|
||||
|
||||
/*! \struct rlc_am_control_pdu_info_t
|
||||
* \brief Structure containing Status PDU information element.
|
||||
*/
|
||||
typedef struct rlc_am_control_pdu_info {
|
||||
uint16_t d_c:1; /*!< \brief Data/Control field. */
|
||||
uint16_t cpt:3; /*!< \brief Control PDU type. */
|
||||
uint16_t ack_sn:10; /*!< \brief Acknowledgment SN field. */
|
||||
uint16_t e1:1; /*!< \brief Extension bit 1 field. */
|
||||
uint16_t dummy:2; /*!< \brief Unused bits. */
|
||||
uint16_t num_nack; /*!< \brief Number of nack_sn_t fields in nack_list[]. */
|
||||
nack_sn_t nack_list[RLC_AM_MAX_NACK_IN_STATUS_PDU]; /*!< \brief List of NACK_SN fields. */
|
||||
} rlc_am_control_pdu_info_t ;
|
||||
|
||||
/*! \struct rlc_am_e_li_t
|
||||
* \brief Structure helping coding and decoding LI and e bits in AMD PDUs and AMD PDU segments.
|
||||
*/
|
||||
typedef struct rlc_am_e_li {
|
||||
uint8_t b1; /*!< \brief 1st byte. */
|
||||
uint8_t b2; /*!< \brief 2nd byte. */
|
||||
uint8_t b3; /*!< \brief 3rd byte. */
|
||||
} rlc_am_e_li_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
/*! \struct rlc_am_pdu_sn_10_t
|
||||
* \brief Structure helping coding and decoding the first 2 bytes of a AMD PDU or AMD PDU segment.
|
||||
*/
|
||||
typedef struct rlc_am_pdu_sn_10 {
|
||||
uint8_t b1; /*!< \brief 1st byte. */
|
||||
uint8_t b2; /*!< \brief 2nd byte. */
|
||||
uint8_t data[2];/*!< \brief Following bytes. */
|
||||
} __attribute__((__packed__)) rlc_am_pdu_sn_10_t ;
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_receiver_impl_
|
||||
* @{
|
||||
*/
|
||||
/*! \struct rlc_am_pdu_info_t
|
||||
* \brief Structure for storing decoded informations from the header of a AMD PDU or AMD PDU segment.
|
||||
*/
|
||||
typedef struct rlc_am_pdu_info {
|
||||
uint32_t d_c:1; /*!< \brief Data/Control field. */
|
||||
uint32_t rf:1; /*!< \brief Resegmentation Flag field. */
|
||||
uint32_t p:1; /*!< \brief Polling bit field. */
|
||||
uint32_t fi:2; /*!< \brief Framing Info field. */
|
||||
uint32_t e:1; /*!< \brief Extension bit field. */
|
||||
uint32_t sn:10; /*!< \brief Sequence Number field. */
|
||||
uint32_t lsf:1; /*!< \brief Last Segment Flag field. */
|
||||
uint32_t so:15; /*!< \brief Segment Offset field. */
|
||||
uint16_t num_li; /*!< \brief Number of Length Indicators. */
|
||||
int16_t li_list[RLC_AM_MAX_SDU_IN_PDU]; /*!< \brief List of Length Indicators. */
|
||||
int16_t hidden_size /*!< \brief Part of payload size in bytes that is not included in the sum of LI fields. */;
|
||||
uint8_t* payload; /*!< \brief Pointer on PDU payload. */
|
||||
int16_t payload_size;/*!< \brief Size of payload in bytes. */
|
||||
int16_t header_size; /*!< \brief Size of header in bytes (including SO field and LI fields). */
|
||||
} rlc_am_pdu_info_t ;
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup _rlc_am_timers_impl_
|
||||
* @{
|
||||
*/
|
||||
/*! \struct rlc_am_timer_t
|
||||
* \brief Generic structure for implementing a timer.
|
||||
*/
|
||||
typedef struct rlc_am_timer {
|
||||
uint32_t ms_time_out; /*!< \brief When set, indicate the time in milliseconds the timer will time-out. */
|
||||
uint32_t ms_start; /*!< \brief indicate the time in milliseconds the timer has been started. */
|
||||
uint32_t ms_duration; /*!< \brief Configured timer duration in milliseconds. */
|
||||
uint32_t running:1; /*!< \brief The timer is running. */
|
||||
uint32_t timed_out:1; /*!< \brief The timer has timed-out. */
|
||||
uint32_t dummy:30; /*!< \brief Bits not used. */
|
||||
} rlc_am_timer_t ;
|
||||
/** @} */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DATA PDU
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* @addtogroup _rlc_am_internal_receiver_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef enum rlc_am_rx_segment_reassemble_info
|
||||
{
|
||||
/** No Reassembly scheduled */
|
||||
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO = 0,
|
||||
/** Reassembly scheduled */
|
||||
RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING = 1,
|
||||
/** Reassembly done */
|
||||
RLC_AM_RX_PDU_SEGMENT_REASSEMBLED = 2
|
||||
|
||||
} rlc_am_rx_segment_reassemble_info_t;
|
||||
|
||||
/*! \struct rlc_am_rx_pdu_management_t
|
||||
* \brief Structure for storing decoded informations from the header of a AMD PDU or AMD PDU segment and information on reassembly.
|
||||
*/
|
||||
typedef struct rlc_am_rx_pdu_management {
|
||||
rlc_am_pdu_info_t pdu_info; /*!< \brief Field for storing decoded informations from the header of a AMD PDU or AMD PDU segment. */
|
||||
uint8_t all_segments_received; /*!< \brief Is all segments of PDU SN have been received. */
|
||||
rlc_am_rx_segment_reassemble_info_t segment_reassembled; /*!< \brief if the segment for SN=vrR is reassembled but not discarded yet. */
|
||||
} rlc_am_rx_pdu_management_t;
|
||||
/** @} */
|
||||
|
||||
typedef enum rlc_am_rx_pdu_status
|
||||
{
|
||||
/** PDU okay. */
|
||||
RLC_AM_DATA_PDU_STATUS_OK = 0,
|
||||
/** SN outside RX window */
|
||||
RLC_AM_DATA_PDU_STATUS_SN_OUTSIDE_WINDOW = 1,
|
||||
/** SN already available */
|
||||
RLC_AM_DATA_PDU_STATUS_SN_DUPLICATE = 2,
|
||||
/** SN already available */
|
||||
RLC_AM_DATA_PDU_STATUS_AM_SEGMENT_DUPLICATE = 3,
|
||||
/** Buffer full */
|
||||
RLC_AM_DATA_PDU_STATUS_BUFFER_FULL = 4,
|
||||
/** Header Error (LI,SO...) */
|
||||
RLC_AM_DATA_PDU_STATUS_HEADER_ERROR = 5,
|
||||
/** Unknown bearer */
|
||||
RLC_AM_DATA_PDU_STATUS_INVALID_BEARER = 6,
|
||||
/** RLC in wrong state */
|
||||
RLC_AM_DATA_PDU_STATUS_WRONG_STATE = 7
|
||||
|
||||
} rlc_am_rx_pdu_status_t;
|
||||
|
||||
/*! \cond PRIVATE */
|
||||
//-----------------------------------------------------------------------------
|
||||
// interlayers optimizations
|
||||
//-----------------------------------------------------------------------------
|
||||
struct rlc_am_tx_data_pdu_allocation {
|
||||
union {
|
||||
struct rlc_am_tx_data_pdu_management rlc_am_tx_pdu_mngmnt;
|
||||
struct mac_tb_req tb_req;
|
||||
struct mac_tx_tb_management tb_mngt;
|
||||
} dummy;
|
||||
};
|
||||
|
||||
/*struct rlc_am_tx_control_pdu_allocation {
|
||||
union {
|
||||
struct mac_tb_req tb_req;
|
||||
struct mac_tx_tb_management tb_mngt;
|
||||
} dummy;
|
||||
};*/
|
||||
|
||||
struct rlc_am_data_req_alloc { // alloc enought bytes for sdu mngt also
|
||||
union {
|
||||
struct rlc_am_data_req dummy1;
|
||||
struct rlc_am_tx_sdu_management dummy2;
|
||||
} dummy;
|
||||
};
|
||||
/*! \endcond */
|
||||
# endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_test.h
|
||||
* \brief This file defines the prototypes of RLC AM test functions.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \company Eurecom
|
||||
* \email: lionel.gauthier@eurecom.fr
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
# ifndef __RLC_AM_TEST_H__
|
||||
# define __RLC_AM_TEST_H__
|
||||
rlc_am_entity_t g_am_tx;
|
||||
rlc_am_entity_t g_am_rx;
|
||||
|
||||
void rlc_am_v9_3_0_test_windows();
|
||||
void rlc_am_v9_3_0_test_read_write_bit_field();
|
||||
void rlc_am_v9_3_0_test_data_conf(module_id_t module_idP, rb_id_t rb_idP, mui_t muiP, rlc_tx_status_t statusP);
|
||||
void rlc_am_v9_3_0_test_send_sdu(rlc_am_entity_t *am_txP, int sdu_indexP);
|
||||
void rlc_am_v9_3_0_test_exchange_pdus(rlc_am_entity_t *am_txP,rlc_am_entity_t *am_RxP,
|
||||
uint16_t bytes_txP,uint16_t bytes_rxP);
|
||||
void rlc_am_v9_3_0_test_mac_rlc_loop (struct mac_data_ind *data_indP, struct mac_data_req *data_requestP, int* drop_countP, int *tx_packetsP, int* dropped_tx_packetsP);
|
||||
void rlc_am_v9_3_0_test_data_ind (module_id_t module_idP, rb_id_t rb_idP, sdu_size_t sizeP,
|
||||
mem_block_t *sduP);
|
||||
void rlc_am_v9_3_0_test_tx_rx();
|
||||
void rlc_am_v9_3_0_test_print_trace (void);
|
||||
void rlc_am_v9_3_0_test();
|
||||
# endif
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_TIMER_POLL_RETRANSMIT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
//#include "rtos_header.h"
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_check_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP
|
||||
)
|
||||
{
|
||||
// 5.2.2.3 Expiry of t-PollRetransmit
|
||||
// Upon expiry of t-PollRetransmit, the transmitting side of an AM RLC entity shall:
|
||||
// - if both the transmission buffer and the retransmission buffer are empty (excluding transmitted RLC data PDU
|
||||
// awaiting for acknowledgements); or
|
||||
// - if no new RLC data PDU can be transmitted (e.g. due to window stalling):
|
||||
// - consider the AMD PDU with SN = VT(S) – 1 for retransmission; or
|
||||
// - consider any AMD PDU which has not been positively acknowledged for retransmission;
|
||||
// - include a poll in a RLC data PDU as described in section 5.2.2.1.
|
||||
|
||||
if (rlc_pP->t_poll_retransmit.running) {
|
||||
if (
|
||||
// CASE 1: start time out
|
||||
// +-----------+------------------+----------+
|
||||
// | |******************| |
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX
|
||||
((rlc_pP->t_poll_retransmit.ms_start < rlc_pP->t_poll_retransmit.ms_time_out) &&
|
||||
((PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_poll_retransmit.ms_time_out) ||
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_poll_retransmit.ms_start))) ||
|
||||
// CASE 2: time out start
|
||||
// +-----------+------------------+----------+
|
||||
// |***********| |**********|
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX VALUE
|
||||
((rlc_pP->t_poll_retransmit.ms_start > rlc_pP->t_poll_retransmit.ms_time_out) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_poll_retransmit.ms_start) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_poll_retransmit.ms_time_out))
|
||||
) {
|
||||
//if (rlc_pP->t_poll_retransmit.frame_time_out <= ctxt_pP->frame) {
|
||||
rlc_pP->t_poll_retransmit.running = 0;
|
||||
rlc_pP->t_poll_retransmit.timed_out = 1;
|
||||
rlc_pP->stat_timer_poll_retransmit_timed_out += 1;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
|
||||
/* Check for any retransmittable PDU if Buffer Occupancy empty or window stall */
|
||||
if (((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
|
||||
(rlc_pP->vt_s == rlc_pP->vt_ms)) {
|
||||
// force BO to be > 0
|
||||
rlc_sn_t sn = RLC_AM_PREV_SN(rlc_pP->vt_s);
|
||||
rlc_sn_t sn_end = RLC_AM_PREV_SN(rlc_pP->vt_a);
|
||||
rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p;
|
||||
|
||||
/* Look for the first retransmittable PDU starting from vtS - 1 */
|
||||
while (sn != sn_end) {
|
||||
tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[sn % RLC_AM_WINDOW_SIZE];
|
||||
//AssertFatal (tx_data_pdu_buffer_p->mem_block != NULL, "RLC AM Tpoll Retx expiry sn=%d ack=%d is empty vtA=%d vtS=%d LcId=%d\n",
|
||||
// sn, tx_data_pdu_buffer_p->flags.ack,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
if(tx_data_pdu_buffer_p->mem_block == NULL){
|
||||
LOG_E(RLC, "RLC AM Tpoll Retx expiry sn=%d ack=%d is empty vtA=%d vtS=%d LcId=%d\n",
|
||||
sn, tx_data_pdu_buffer_p->flags.ack,rlc_pP->vt_a,rlc_pP->vt_s,rlc_pP->channel_id);
|
||||
sn = RLC_AM_PREV_SN(sn);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((tx_data_pdu_buffer_p->flags.ack == 0) && (tx_data_pdu_buffer_p->flags.max_retransmit == 0)) {
|
||||
tx_data_pdu_buffer_p->flags.retransmit = 1;
|
||||
tx_data_pdu_buffer_p->retx_payload_size = tx_data_pdu_buffer_p->payload_size;
|
||||
if (tx_data_pdu_buffer_p->retx_count == tx_data_pdu_buffer_p->retx_count_next) {
|
||||
tx_data_pdu_buffer_p->retx_count_next ++;
|
||||
}
|
||||
rlc_pP->retrans_num_pdus += 1;
|
||||
rlc_pP->retrans_num_bytes_to_retransmit += tx_data_pdu_buffer_p->payload_size;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] TIME-OUT PUT SN=%d in ReTx Buffer\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),tx_data_pdu_buffer_p->sn);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sn = RLC_AM_PREV_SN(sn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rlc_pP->force_poll = true;
|
||||
//BugFix : new ms_time_out is computed when next poll is transmitter
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_am_is_timer_poll_retransmit_timed_out(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP
|
||||
)
|
||||
{
|
||||
return rlc_pP->t_poll_retransmit.timed_out;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_stop_and_reset_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP
|
||||
)
|
||||
{
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] STOPPED AND RESET\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_pP->t_poll_retransmit.running = 0;
|
||||
rlc_pP->t_poll_retransmit.ms_time_out = 0;
|
||||
rlc_pP->t_poll_retransmit.ms_start = 0;
|
||||
rlc_pP->t_poll_retransmit.timed_out = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_start_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP
|
||||
)
|
||||
{
|
||||
/* Stop timer if it was previously running */
|
||||
rlc_am_stop_and_reset_timer_poll_retransmit(ctxt_pP,rlc_pP);
|
||||
|
||||
if (rlc_pP->t_poll_retransmit.ms_duration > 0) {
|
||||
rlc_pP->t_poll_retransmit.running = 1;
|
||||
rlc_pP->t_poll_retransmit.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_poll_retransmit.ms_duration;
|
||||
rlc_pP->t_poll_retransmit.ms_start = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] STARTED (TIME-OUT = FRAME %05d)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->t_poll_retransmit.ms_time_out);
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T_POLL_RETRANSMIT] NOT STARTED, CAUSE CONFIGURED 0 ms\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_init_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
const uint32_t ms_durationP)
|
||||
{
|
||||
rlc_pP->t_poll_retransmit.running = 0;
|
||||
rlc_pP->t_poll_retransmit.ms_time_out = 0;
|
||||
rlc_pP->t_poll_retransmit.ms_start = 0;
|
||||
rlc_pP->t_poll_retransmit.ms_duration = ms_durationP;
|
||||
rlc_pP->t_poll_retransmit.timed_out = 0;
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_timer_poll_retransmit.h
|
||||
* \brief This file defines the prototypes of the functions manipulating the t-PollRetransmit timer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_timers_impl_ RLC AM Timers Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __RLC_AM_TIMER_POLL_RETRANSMIT_H__
|
||||
# define __RLC_AM_TIMER_POLL_RETRANSMIT_H__
|
||||
|
||||
/*! \fn void rlc_am_check_timer_poll_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Check if timer Poll-retransmit has timed-out, if so it is stopped and has the status "timed-out".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
|
||||
*/
|
||||
void rlc_am_check_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn int rlc_am_is_timer_poll_retransmit_timed_out(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Boolean function, check if timer Poll-retransmit has timed-out.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \return 1 if timer Poll-retransmit has timed-out, else 0.
|
||||
*/
|
||||
int rlc_am_is_timer_poll_retransmit_timed_out(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_stop_and_reset_timer_poll_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Stop and reset the timer Poll-retransmit.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
|
||||
*/
|
||||
void rlc_am_stop_and_reset_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_start_timer_poll_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Re-arm (based on RLC AM config parameter) and start timer Poll-retransmit.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] frame Frame index
|
||||
*/
|
||||
void rlc_am_start_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_init_timer_poll_retransmit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, const uint32_t time_outP)
|
||||
* \brief Initialize the timer Poll-retransmit with RLC AM time-out config parameter.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] time_outP Time-out in frame units.
|
||||
*/
|
||||
void rlc_am_init_timer_poll_retransmit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP,
|
||||
const uint32_t time_outP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_TIMER_POLL_REORDERING_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
# include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils//LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_check_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
|
||||
if (rlc_pP->t_reordering.running) {
|
||||
if (
|
||||
// CASE 1: start time out
|
||||
// +-----------+------------------+----------+
|
||||
// | |******************| |
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX
|
||||
((rlc_pP->t_reordering.ms_start < rlc_pP->t_reordering.ms_time_out) &&
|
||||
((PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_reordering.ms_time_out) ||
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_reordering.ms_start))) ||
|
||||
// CASE 2: time out start
|
||||
// +-----------+------------------+----------+
|
||||
// |***********| |**********|
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX VALUE
|
||||
((rlc_pP->t_reordering.ms_start > rlc_pP->t_reordering.ms_time_out) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_reordering.ms_start) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_reordering.ms_time_out))
|
||||
) {
|
||||
//if (rlc_pP->t_reordering.frame_time_out == ctxt_pP->frame) {
|
||||
// 5.1.3.2.4 Actions when t-Reordering expires
|
||||
// When t-Reordering expires, the receiving side of an AM RLC entity shall:
|
||||
// - update VR(MS) to the SN of the first AMD PDU with SN >= VR(X) for which not all byte segments have been
|
||||
// received;
|
||||
// - if VR(H) > VR(MS):
|
||||
// - start t-Reordering;
|
||||
// - set VR(X) to VR(H).
|
||||
|
||||
//AssertFatal (rlc_pP->vr_x != RLC_SN_UNDEFINED, "RLC AM TReordering Expiry vrX not defined LcId=%d\n", rlc_pP->channel_id);
|
||||
if(rlc_pP->vr_x == RLC_SN_UNDEFINED){
|
||||
LOG_E(RLC, "RLC AM TReordering Expiry vrX not defined LcId=%d\n", rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
rlc_pP->t_reordering.running = 0;
|
||||
rlc_pP->t_reordering.timed_out = 1;
|
||||
rlc_pP->stat_timer_reordering_timed_out += 1;
|
||||
|
||||
rlc_am_pdu_info_t* pdu_info;
|
||||
mem_block_t* cursor;
|
||||
cursor = rlc_pP->receiver_buffer.head;
|
||||
rlc_usn_t vr_ms_new = rlc_pP->vr_x;
|
||||
|
||||
//AssertFatal (cursor != NULL, "RLC AM TReordering Expiry Rx PDU list empty LcId=%d\n", rlc_pP->channel_id);
|
||||
if(cursor == NULL){
|
||||
LOG_E(RLC, "RLC AM TReordering Expiry Rx PDU list empty LcId=%d\n", rlc_pP->channel_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* go to memblock up to vrX*/
|
||||
pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info;
|
||||
while ((cursor != NULL) && (RLC_AM_DIFF_SN(pdu_info->sn,rlc_pP->vr_r) < RLC_AM_DIFF_SN(vr_ms_new,rlc_pP->vr_r))) {
|
||||
cursor = cursor->next;
|
||||
if (cursor != NULL) {
|
||||
pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now find a SN for which either no PDU is received or partially received */
|
||||
while ((cursor != NULL) && (vr_ms_new != rlc_pP->vr_h) && (pdu_info->sn == vr_ms_new) && (((rlc_am_rx_pdu_management_t*)(cursor->data))->all_segments_received > 0)) {
|
||||
/* Increment vrMS if the PDU is fully received or if this is the last PDU segment */
|
||||
if ((pdu_info->rf == 0) || (pdu_info->lsf == 1)) {
|
||||
vr_ms_new = RLC_AM_NEXT_SN(vr_ms_new);
|
||||
}
|
||||
cursor = cursor->next;
|
||||
if (cursor != NULL) {
|
||||
pdu_info = &((rlc_am_rx_pdu_management_t*)(cursor->data))->pdu_info;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update vr_ms */
|
||||
rlc_pP->vr_ms = vr_ms_new;
|
||||
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT UPDATED VR(MS) %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_ms);
|
||||
|
||||
/* if new vrMS is lower than vrH, update vrX and restart timerReordering */
|
||||
if (rlc_pP->vr_ms != rlc_pP->vr_h) {
|
||||
rlc_pP->vr_x = rlc_pP->vr_h;
|
||||
rlc_pP->t_reordering.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_reordering.ms_duration;
|
||||
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] TIME-OUT, RESTARTED T-REORDERING, UPDATED VR(X) to VR(R) %04d\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->vr_x);
|
||||
}
|
||||
|
||||
/* Trigger a STATUS report */
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_T_REORDERING);
|
||||
// Clear Delay flag if it was setup as it is useless due to Status PDU to be sent for TReordering expiry
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_TRIGGERED_DELAYED);
|
||||
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_stop_and_reset_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] STOPPED AND RESET\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_pP->t_reordering.running = 0;
|
||||
rlc_pP->t_reordering.ms_time_out = 0;
|
||||
rlc_pP->t_reordering.ms_start = 0;
|
||||
rlc_pP->t_reordering.timed_out = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_start_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
rlc_pP->t_reordering.timed_out = 0;
|
||||
|
||||
if (rlc_pP->t_reordering.running == 0){
|
||||
if (rlc_pP->t_reordering.ms_duration > 0) {
|
||||
rlc_pP->t_reordering.running = 1;
|
||||
rlc_pP->t_reordering.ms_time_out = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) + rlc_pP->t_reordering.ms_duration;
|
||||
rlc_pP->t_reordering.ms_start = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] STARTED (TIME-OUT = %5u ms)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->t_reordering.ms_time_out);
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-REORDERING] NOT STARTED, CAUSE CONFIGURED 0 ms\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_init_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP,
|
||||
const uint32_t ms_durationP)
|
||||
{
|
||||
rlc_pP->t_reordering.running = 0;
|
||||
rlc_pP->t_reordering.ms_time_out = 0;
|
||||
rlc_pP->t_reordering.ms_start = 0;
|
||||
rlc_pP->t_reordering.ms_duration = ms_durationP;
|
||||
rlc_pP->t_reordering.timed_out = 0;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_timer_reordering.h
|
||||
* \brief This file defines the prototypes of the functions manipulating the t-Reordering timer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_timers_impl_ RLC AM Timers Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_TIMER_REORDERING_H__
|
||||
# define __RLC_AM_TIMER_REORDERING_H__
|
||||
|
||||
/*! \fn void rlc_am_check_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Check if timer reordering has timed-out, if so it is stopped and has the status "timed-out".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_check_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_stop_and_reset_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Stop and reset the timer reordering.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_stop_and_reset_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_start_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Re-arm (based on RLC AM config parameter) and start timer reordering.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_start_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_init_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, const uint32_t time_outP)
|
||||
* \brief Initialize the timer reordering with RLC AM time-out config parameter.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] time_outP Time-out in frameP units.
|
||||
*/
|
||||
void rlc_am_init_timer_reordering(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t* const rlc_pP,
|
||||
const uint32_t time_outP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_TIMER_STATUS_PROHIBIT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_check_timer_status_prohibit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t * const rlc_pP)
|
||||
{
|
||||
if (rlc_pP->t_status_prohibit.ms_duration > 0) {
|
||||
if (rlc_pP->t_status_prohibit.running) {
|
||||
if (
|
||||
// CASE 1: start time out
|
||||
// +-----------+------------------+----------+
|
||||
// | |******************| |
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX
|
||||
((rlc_pP->t_status_prohibit.ms_start < rlc_pP->t_status_prohibit.ms_time_out) &&
|
||||
((PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_status_prohibit.ms_time_out) ||
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_status_prohibit.ms_start))) ||
|
||||
// CASE 2: time out start
|
||||
// +-----------+------------------+----------+
|
||||
// |***********| |**********|
|
||||
// +-----------+------------------+----------+
|
||||
//FRAME # 0 FRAME MAX VALUE
|
||||
((rlc_pP->t_status_prohibit.ms_start > rlc_pP->t_status_prohibit.ms_time_out) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) < rlc_pP->t_status_prohibit.ms_start) &&
|
||||
(PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP) >= rlc_pP->t_status_prohibit.ms_time_out))
|
||||
) {
|
||||
|
||||
//if ((rlc_pP->t_status_prohibit.frame_time_out <= ctxt_pP->frame) && (rlc_pP->t_status_prohibit.frame_start)) {
|
||||
rlc_pP->t_status_prohibit.running = 0;
|
||||
rlc_pP->t_status_prohibit.timed_out = 1;
|
||||
rlc_pP->stat_timer_status_prohibit_timed_out += 1;
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-STATUS-PROHIBIT] TIME-OUT\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
//#warning TO DO rlc_am_check_timer_status_prohibit
|
||||
rlc_am_stop_and_reset_timer_status_prohibit(ctxt_pP, rlc_pP);
|
||||
/* Clear StatusProhibit flag */
|
||||
RLC_AM_CLEAR_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT);
|
||||
//rlc_pP->t_status_prohibit.frame_time_out = ctxt_pP->frame + rlc_pP->t_status_prohibit.time_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_stop_and_reset_timer_status_prohibit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
)
|
||||
{
|
||||
if (rlc_pP->t_status_prohibit.ms_duration > 0) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-STATUS-PROHIBIT] STOPPED AND RESET\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_pP->t_status_prohibit.running = 0;
|
||||
rlc_pP->t_status_prohibit.ms_time_out = 0;
|
||||
rlc_pP->t_status_prohibit.ms_start = 0;
|
||||
rlc_pP->t_status_prohibit.timed_out = 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_am_start_timer_status_prohibit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP
|
||||
)
|
||||
{
|
||||
rlc_pP->t_status_prohibit.timed_out = 0;
|
||||
|
||||
if (rlc_pP->t_status_prohibit.running == 0){
|
||||
if (rlc_pP->t_status_prohibit.ms_duration > 0) {
|
||||
rlc_pP->t_status_prohibit.running = 1;
|
||||
rlc_pP->t_status_prohibit.ms_time_out = rlc_pP->t_status_prohibit.ms_duration + PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
|
||||
rlc_pP->t_status_prohibit.ms_start = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP);
|
||||
RLC_AM_SET_STATUS(rlc_pP->status_requested,RLC_AM_STATUS_PROHIBIT);
|
||||
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-STATUS-PROHIBIT] STARTED (TIME-OUT = %u ms)\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->t_status_prohibit.ms_time_out);
|
||||
LOG_D(RLC, "TIME-OUT = FRAME %u\n", rlc_pP->t_status_prohibit.ms_time_out);
|
||||
} else {
|
||||
LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[T-STATUS-PROHIBIT] NOT STARTED, CAUSE CONFIGURED 0 ms\n",
|
||||
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_am_init_timer_status_prohibit(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_am_entity_t *const rlc_pP,
|
||||
const uint32_t ms_durationP)
|
||||
{
|
||||
rlc_pP->t_status_prohibit.running = 0;
|
||||
rlc_pP->t_status_prohibit.ms_time_out = 0;
|
||||
rlc_pP->t_status_prohibit.ms_start = 0;
|
||||
rlc_pP->t_status_prohibit.ms_duration = ms_durationP;
|
||||
rlc_pP->t_status_prohibit.timed_out = 0;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_timer_status_prohibit.h
|
||||
* \brief This file defines the prototypes of the functions manipulating the t-StatusProhibit timer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_timers_impl_ RLC AM Timers Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
#ifndef __RLC_AM_TIMER_STATUS_PROHIBIT_H__
|
||||
# define __RLC_AM_TIMER_STATUS_PROHIBIT_H__
|
||||
|
||||
|
||||
/*! \fn void rlc_am_check_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Check if timer status-prohibit has timed-out, if so it is stopped and has the status "timed-out".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_check_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_stop_and_reset_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Stop and reset the timer status-prohibit.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_stop_and_reset_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_start_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP)
|
||||
* \brief Re-arm (based on RLC AM config parameter) and start timer status-prohibit.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
*/
|
||||
void rlc_am_start_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_am_init_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, const uint32_t time_outP)
|
||||
* \brief Initialize the timer status-prohibit with RLC AM time-out config parameter.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] time_outP Time-out in frameP units.
|
||||
*/
|
||||
void rlc_am_init_timer_status_prohibit(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlc_pP, const uint32_t time_outP);
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_AM_MODULE 1
|
||||
#define RLC_AM_WINDOWS_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <assert.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_am.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int rlc_am_in_tx_window(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if (snP >= RLC_AM_SN_MODULO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(snP - rlc_pP->vt_a)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(rlc_pP->vt_ms - rlc_pP->vt_a)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if ((shifted_sn >= 0) && (shifted_sn < upper_bound)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_in_rx_window(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if (snP >= RLC_AM_SN_MODULO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(snP - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(rlc_pP->vr_mr - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if ((shifted_sn >= 0) && (shifted_sn < upper_bound)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_sn_gte_vr_h(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if (snP >= RLC_AM_SN_MODULO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(snP - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(rlc_pP->vr_h - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if (shifted_sn >= upper_bound) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int rlc_am_sn_gte_vr_x(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if (snP >= RLC_AM_SN_MODULO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(snP - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(rlc_pP->vr_x - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if (shifted_sn >= upper_bound) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_sn_gt_vr_ms(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if (snP >= RLC_AM_SN_MODULO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(snP - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(rlc_pP->vr_ms - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if (shifted_sn > upper_bound) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_tx_sn1_gt_sn2(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t sn1P,
|
||||
const rlc_sn_t sn2P)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if ((sn1P >= RLC_AM_SN_MODULO) || (sn2P >= RLC_AM_SN_MODULO)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(sn1P - rlc_pP->vt_a)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(sn2P - rlc_pP->vt_a)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if (shifted_sn > upper_bound) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
signed int
|
||||
rlc_am_rx_sn1_gt_sn2(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t sn1P,
|
||||
const rlc_sn_t sn2P)
|
||||
{
|
||||
rlc_usn_t shifted_sn;
|
||||
rlc_usn_t upper_bound;
|
||||
|
||||
if ((sn1P >= RLC_AM_SN_MODULO) || (sn2P >= RLC_AM_SN_MODULO)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shifted_sn = ((rlc_usn_t)(sn1P - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
upper_bound = ((rlc_usn_t)(sn2P - rlc_pP->vr_r)) % RLC_AM_SN_MODULO;
|
||||
|
||||
if (shifted_sn > upper_bound) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_am_windows.h
|
||||
* \brief This file defines the prototypes of the functions testing window, based on SN modulo and rx and tx protocol state variables.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_am_windowing_impl_ RLC AM Windowing Reference Implementation
|
||||
* @ingroup _rlc_am_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_AM_WINDOWS_H__
|
||||
# define __RLC_AM_WINDOWS_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \fn signed int rlc_am_in_tx_window(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Boolean function, check if sequence number is VT(A) <= snP < VT(MS).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return 1 if snP in tx window, else 0.
|
||||
*/
|
||||
signed int rlc_am_in_tx_window(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn signed int rlc_am_in_rx_window(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Boolean function, check if sequence number is VR(R) <= snP < VR(MR).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return 1 if snP in rx window, else 0.
|
||||
*/
|
||||
signed int rlc_am_in_rx_window(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn signed int rlc_am_sn_gte_vr_h (const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Boolean function, check if sequence number is greater than or equal VR(R).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return 1 if sequence number is greater than or equal VR(R), else 0.
|
||||
*/
|
||||
signed int rlc_am_sn_gte_vr_h (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn signed int rlc_am_sn_gte_vr_x (const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Boolean function, check if sequence number is greater than or equal VR(X).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return 1 if sequence number is greater than or equal VR(X), else 0.
|
||||
*/
|
||||
signed int rlc_am_sn_gte_vr_x (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn signed int rlc_am_sn_gt_vr_ms (const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Boolean function, check if sequence number is greater than VR(MS).
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return 1 if sequence number is greater than VR(MS), else 0.
|
||||
*/
|
||||
signed int rlc_am_sn_gt_vr_ms(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t snP);
|
||||
|
||||
/*! \fn signed int rlc_am_tx_sn1_gt_sn2 (const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t sn1P, const rlc_sn_t sn2P)
|
||||
* \brief Boolean function, in the context of the tx window, check if sn1P is greater than sn2P.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] sn1P Sequence number.
|
||||
* \param[in] sn2P Sequence number.
|
||||
* \return 1 if sn1P is greater than sn2P, else 0.
|
||||
*/
|
||||
signed int rlc_am_tx_sn1_gt_sn2(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t sn1P,
|
||||
const rlc_sn_t sn2P);
|
||||
|
||||
/*! \fn signed int rlc_am_rx_sn1_gt_sn2(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP, const rlc_sn_t sn1P, const rlc_sn_t sn2P)
|
||||
* \brief Boolean function, in the context of the rx window, check if sn1P is greater than sn2P.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC AM protocol instance pointer.
|
||||
* \param[in] sn1P Sequence number.
|
||||
* \param[in] sn2P Sequence number.
|
||||
* \return 1 if sn1P is greater than sn2P, else 0.
|
||||
*/
|
||||
signed int rlc_am_rx_sn1_gt_sn2(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_am_entity_t* const rlc_pP,
|
||||
const rlc_sn_t sn1P,
|
||||
const rlc_sn_t sn2P);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_TM_MODULE 1
|
||||
#define RLC_TM_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_tm.h"
|
||||
#include "mac_primitives.h"
|
||||
#include "rlc_primitives.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_tm_send_sdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlc_pP,
|
||||
const bool error_indicationP,
|
||||
uint8_t * const srcP,
|
||||
const sdu_size_t length_in_bitsP)
|
||||
{
|
||||
int length_in_bytes;
|
||||
#if DEBUG_RLC_TM_DISPLAY_ASCII_DATA
|
||||
int index;
|
||||
#endif
|
||||
#if DEBUG_RLC_TM_REASSEMBLY
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEND_SDU] %d bits\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP),
|
||||
length_in_bitsP);
|
||||
#endif
|
||||
length_in_bytes = (length_in_bitsP + 7) >> 3;
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction == NULL) {
|
||||
rlc_pP->output_sdu_in_construction = get_free_mem_block (length_in_bytes, __func__);
|
||||
}
|
||||
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
#if DEBUG_RLC_TM_DISPLAY_ASCII_DATA
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEND_SDU] DATA :",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
|
||||
for (index = 0; index < length_in_bytes; index++) {
|
||||
LOG_T (RLC,"%c", srcP[index]);
|
||||
}
|
||||
|
||||
LOG_T (RLC,"\n");
|
||||
#endif
|
||||
|
||||
memcpy (&rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write], srcP, length_in_bytes);
|
||||
|
||||
rlc_data_ind (
|
||||
ctxt_pP,
|
||||
BOOL_NOT(rlc_pP->is_data_plane),
|
||||
MBMS_FLAG_NO,
|
||||
rlc_pP->rb_id,
|
||||
length_in_bytes,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
rlc_pP->output_sdu_in_construction = NULL;
|
||||
} else {
|
||||
LOG_D (RLC,"[RLC_TM %p][SEND_SDU] ERROR OUTPUT SDU IS NULL\n", rlc_pP);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_no_segment (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t *const rlc_pP
|
||||
)
|
||||
{
|
||||
mem_block_t *pdu_p = NULL;
|
||||
struct rlc_tm_tx_sdu_management *sdu_mngt_p = NULL;
|
||||
struct rlc_tm_tx_pdu_management *pdu_mngt_p = NULL;
|
||||
int nb_pdu_to_transmit = 1;
|
||||
|
||||
// only one SDU per TTI
|
||||
while ((rlc_pP->input_sdus[rlc_pP->current_sdu_index]) && (nb_pdu_to_transmit > 0)) {
|
||||
|
||||
sdu_mngt_p = ((struct rlc_tm_tx_sdu_management *) (rlc_pP->input_sdus[rlc_pP->current_sdu_index]->data));
|
||||
|
||||
if (!(pdu_p = get_free_mem_block (((rlc_pP->rlc_pdu_size + 7) >> 3) + sizeof (struct rlc_tm_tx_data_pdu_struct) + GUARD_CRC_LIH_SIZE, __func__))) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT"[SEGMENT] ERROR COULD NOT GET NEW PDU, EXIT\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
return;
|
||||
}
|
||||
|
||||
// SHOULD BE OPTIMIZED...SOON
|
||||
pdu_mngt_p = (struct rlc_tm_tx_pdu_management *) (pdu_p->data);
|
||||
memset (pdu_p->data, 0, sizeof (struct rlc_tm_tx_pdu_management));
|
||||
pdu_mngt_p->first_byte = (uint8_t*)&pdu_p->data[sizeof (struct rlc_tm_tx_data_pdu_struct)];
|
||||
|
||||
memcpy (pdu_mngt_p->first_byte, sdu_mngt_p->first_byte, ((rlc_pP->rlc_pdu_size + 7) >> 3));
|
||||
((struct mac_tb_req *) (pdu_p->data))->rlc = NULL;
|
||||
((struct mac_tb_req *) (pdu_p->data))->data_ptr = pdu_mngt_p->first_byte;
|
||||
((struct mac_tb_req *) (pdu_p->data))->first_bit = 0;
|
||||
((struct mac_tb_req *) (pdu_p->data))->tb_size = rlc_pP->rlc_pdu_size >> 3;
|
||||
list_add_tail_eurecom (pdu_p, &rlc_pP->pdus_to_mac_layer);
|
||||
|
||||
rlc_pP->buffer_occupancy -= (sdu_mngt_p->sdu_size >> 3);
|
||||
free_mem_block (rlc_pP->input_sdus[rlc_pP->current_sdu_index], __func__);
|
||||
rlc_pP->input_sdus[rlc_pP->current_sdu_index] = NULL;
|
||||
rlc_pP->current_sdu_index = (rlc_pP->current_sdu_index + 1) % rlc_pP->size_input_sdus_buffer;
|
||||
rlc_pP->nb_sdu -= 1;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_rx (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const argP,
|
||||
struct mac_data_ind data_indP)
|
||||
{
|
||||
|
||||
rlc_tm_entity_t * const rlc_p = (rlc_tm_entity_t *) argP;
|
||||
mem_block_t *tb_p;
|
||||
uint8_t *first_byte_p;
|
||||
|
||||
rlc_p->output_sdu_size_to_write = 0; // size of sdu reassemblied
|
||||
|
||||
while ((tb_p = list_remove_head (&data_indP.data))) {
|
||||
first_byte_p = ((struct mac_tb_ind *) (tb_p->data))->data_ptr;
|
||||
|
||||
((struct rlc_tm_rx_pdu_management *) (tb_p->data))->first_byte = first_byte_p;
|
||||
|
||||
rlc_tm_send_sdu (ctxt_pP, rlc_p, (((struct mac_tb_ind *) (tb_p->data))->error_indication), first_byte_p, data_indP.tb_size);
|
||||
free_mem_block (tb_p, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_status_resp
|
||||
rlc_tm_mac_status_indication (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlc_pP,
|
||||
struct mac_status_ind tx_statusP)
|
||||
{
|
||||
struct mac_status_resp status_resp;
|
||||
|
||||
status_resp.buffer_occupancy_in_bytes = ((rlc_tm_entity_t *) rlc_pP)->buffer_occupancy;
|
||||
status_resp.buffer_occupancy_in_pdus = status_resp.buffer_occupancy_in_bytes / ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size;
|
||||
status_resp.rlc_info.rlc_protocol_state = ((rlc_tm_entity_t *) rlc_pP)->protocol_state;
|
||||
status_resp.head_sdu_creation_time = 0;
|
||||
return status_resp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_data_req
|
||||
rlc_tm_mac_data_request (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlc_pP)
|
||||
{
|
||||
rlc_tm_entity_t* rlc_p = (rlc_tm_entity_t*) rlc_pP;
|
||||
struct mac_data_req data_req;
|
||||
|
||||
rlc_tm_no_segment (ctxt_pP, rlc_p);
|
||||
list_init (&data_req.data, NULL);
|
||||
list_add_list (&rlc_p->pdus_to_mac_layer, &data_req.data);
|
||||
data_req.buffer_occupancy_in_bytes = rlc_p->buffer_occupancy;
|
||||
data_req.buffer_occupancy_in_pdus = data_req.buffer_occupancy_in_bytes / rlc_p->rlc_pdu_size;
|
||||
data_req.rlc_info.rlc_protocol_state = rlc_p->protocol_state;
|
||||
|
||||
if (data_req.data.nb_elements > 0) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" MAC_DATA_REQUEST %d TBs\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
|
||||
data_req.data.nb_elements);
|
||||
}
|
||||
data_req.ue_id_type_indicator = 0;
|
||||
|
||||
return data_req;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_mac_data_indication (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlc_pP,
|
||||
struct mac_data_ind data_indP)
|
||||
{
|
||||
|
||||
if (data_indP.data.nb_elements > 0) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" MAC_DATA_IND %d TBs\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, ((rlc_tm_entity_t*) rlc_pP)),
|
||||
data_indP.data.nb_elements);
|
||||
}
|
||||
|
||||
rlc_tm_rx (ctxt_pP, rlc_pP, data_indP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_data_req (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void *const rlc_pP,
|
||||
mem_block_t *const sdu_pP)
|
||||
{
|
||||
rlc_tm_entity_t *rlc_p = (rlc_tm_entity_t *) rlc_pP;
|
||||
|
||||
#if DEBUG_RLC_TM_DATA_REQUEST
|
||||
LOG_D (RLC, PROTOCOL_RLC_TM_CTXT_FMT" RLC_TM_DATA_REQ size %d Bytes, BO %ld , NB SDU %d current_sdu_index=%d next_sdu_index=%d\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
|
||||
((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
|
||||
rlc_p->buffer_occupancy,
|
||||
rlc_p->nb_sdu,
|
||||
rlc_p->current_sdu_index,
|
||||
rlc_p->next_sdu_index);
|
||||
#endif
|
||||
|
||||
// not in 3GPP specification but the buffer may be full if not correctly configured
|
||||
if (rlc_p->input_sdus[rlc_p->next_sdu_index] == NULL) {
|
||||
((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_tm_data_req *) (sdu_pP->data))->data_size;
|
||||
rlc_p->buffer_occupancy += ((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->sdu_size >> 3;
|
||||
rlc_p->nb_sdu += 1;
|
||||
((struct rlc_tm_tx_sdu_management *) (sdu_pP->data))->first_byte = (uint8_t*)&sdu_pP->data[sizeof (struct rlc_tm_data_req_alloc)];
|
||||
rlc_p->input_sdus[rlc_p->next_sdu_index] = sdu_pP;
|
||||
rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % rlc_p->size_input_sdus_buffer;
|
||||
} else {
|
||||
free_mem_block (sdu_pP, __func__);
|
||||
}
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_tm.h
|
||||
* \brief This file, and only this file must be included by code that interact with RLC TM layer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_tm_impl_ RLC TM Layer Reference Implementation
|
||||
* @ingroup _rlc_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_TM_H__
|
||||
# define __RLC_TM_H__
|
||||
# include "platform_types.h"
|
||||
# include "rlc_def.h"
|
||||
# include "rlc_def_lte.h"
|
||||
# include "rlc_tm_structs.h"
|
||||
# include "rlc_tm_entity.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_tm_init.h"
|
||||
|
||||
#define PROTOCOL_RLC_TM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld]"
|
||||
#define PROTOCOL_RLC_TM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
|
||||
(rLC_Pp->is_data_plane) ? "DRB TM" : "SRB TM",\
|
||||
rLC_Pp->rb_id
|
||||
|
||||
|
||||
/*! \fn void rlc_tm_send_sdu (
|
||||
* const protocol_ctxt_t* const ctxt_pP,
|
||||
* rlc_tm_entity_t * const rlc_pP,
|
||||
* const bool error_indicationP,
|
||||
* uint8_t * const srcP,
|
||||
* const sdu_size_t length_in_bitsP)
|
||||
* \brief Send SDU if any reassemblied to upper layer.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] error_indicationP Error indicated by lower layers for this SDU.
|
||||
* \param[in] srcP SDU data pointer.
|
||||
* \param[in] length_in_bitsP Length of SDU in bits.
|
||||
*/
|
||||
void rlc_tm_send_sdu(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlc_pP,
|
||||
const bool error_indicationP,
|
||||
uint8_t * const srcP,
|
||||
const sdu_size_t length_in_bitsP);
|
||||
|
||||
/*! \fn void rlc_tm_no_segment (const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP)
|
||||
* \brief Schedule a SDU to be transmited by lower layers.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
*/
|
||||
void rlc_tm_no_segment (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t *const rlcP);
|
||||
|
||||
/*! \fn void rlc_tm_rx (const protocol_ctxt_t* const ctxt_pP,void *const rlcP, struct mac_data_ind data_indP)
|
||||
* \brief Process the received PDUs from lower layer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] data_indP PDUs from MAC.
|
||||
*/
|
||||
void rlc_tm_rx (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void *const rlcP,
|
||||
struct mac_data_ind data_indP);
|
||||
|
||||
|
||||
/*! \fn struct mac_status_resp rlc_tm_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void * const rlcP, struct mac_status_ind tx_statusP)
|
||||
* \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU.
|
||||
* \return The maximum number of bytes that can be served by RLC instance to MAC.
|
||||
*/
|
||||
struct mac_status_resp
|
||||
rlc_tm_mac_status_indication (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlc_pP,
|
||||
struct mac_status_ind tx_statusP);
|
||||
|
||||
|
||||
/*! \fn struct mac_data_req rlc_tm_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void * const rlcP)
|
||||
* \brief Gives PDUs to lower layer MAC.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \return A PDU of the previously requested number of bytes, and the updated maximum number of bytes that can be served by RLC instance to MAC for next RLC transmission.
|
||||
*/
|
||||
struct mac_data_req rlc_tm_mac_data_request (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlcP);
|
||||
|
||||
|
||||
/*! \fn void rlc_tm_mac_data_indication (const protocol_ctxt_t* const ctxt_pP,void * const rlcP, struct mac_data_ind data_indP)
|
||||
* \brief Receive PDUs from lower layer MAC.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] data_indP PDUs from MAC.
|
||||
*/
|
||||
void rlc_tm_mac_data_indication (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlcP,
|
||||
struct mac_data_ind data_indP);
|
||||
|
||||
|
||||
/*! \fn void rlc_tm_data_req (const protocol_ctxt_t* const ctxt_pP,void * const rlcP, mem_block_t * const sduP)
|
||||
* \brief Interface with higher layers, buffer higher layer SDUS for transmission.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] sduP SDU. (A struct rlc_tm_data_req is mapped on sduP->data.)
|
||||
*/
|
||||
void rlc_tm_data_req (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
void * const rlcP,
|
||||
mem_block_t * const sduP);
|
||||
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_tm_entity.h
|
||||
* \brief This file defines the RLC TM variables stored in a struct called rlc_tm_entity_t.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note The rlc_tm_entity_t structure store protocol variables, statistic variables, allocation variables, buffers and other miscellaneous variables.
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
# ifndef __RLC_TM_ENTITY_H__
|
||||
# define __RLC_TM_ENTITY_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
# include "rlc_tm_structs.h"
|
||||
# include "rlc_def.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \struct rlc_tm_entity_t
|
||||
* \brief Structure containing a RLC TM instance protocol variables, allocation variables, buffers and other miscellaneous variables.
|
||||
*/
|
||||
typedef struct rlc_tm_entity {
|
||||
bool allocation; /*!< \brief Boolean for rlc_tm_entity_t struct allocation. */
|
||||
rlc_protocol_state_t protocol_state; /*!< \brief Protocol state, can be RLC_NULL_STATE, RLC_DATA_TRANSFER_READY_STATE, RLC_LOCAL_SUSPEND_STATE. */
|
||||
bool is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */
|
||||
bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */
|
||||
// for stats and trace purpose :
|
||||
logical_chan_id_t channel_id; /*!< \brief Transport channel identifier. */
|
||||
rb_id_t rb_id; /*!< \brief Radio bearer identifier, for statistics and trace purpose. */
|
||||
//-----------------------------
|
||||
// tranmission
|
||||
//-----------------------------
|
||||
// sdu communication;
|
||||
mem_block_t **input_sdus; /*!< \brief Input SDU buffer (for SDUs coming from upper layers). Should be accessed as an array. */
|
||||
mem_block_t *input_sdus_alloc; /*!< \brief Allocated memory for the input SDU buffer (for SDUs coming from upper layers). */
|
||||
uint16_t size_input_sdus_buffer; /*!< \brief Size of the input SDU buffer. */
|
||||
uint16_t nb_sdu; /*!< \brief Total number of SDUs in input_sdus[] */
|
||||
uint16_t next_sdu_index; /*!< \brief Next SDU index for a new incomin SDU in input_sdus[]. */
|
||||
uint16_t current_sdu_index; /*!< \brief Current SDU index in input_sdus array to be segmented. */
|
||||
list_t pdus_to_mac_layer; /*!< \brief PDUs buffered for transmission to MAC layer. */
|
||||
sdu_size_t rlc_pdu_size;
|
||||
rlc_buffer_occupancy_t buffer_occupancy; /*!< \brief Number of bytes contained in input_sdus buffer.*/
|
||||
//-----------------------------
|
||||
// receiver
|
||||
//-----------------------------
|
||||
unsigned int output_sdu_size_to_write; /*!< \brief Size of the reassemblied SDU. */
|
||||
mem_block_t *output_sdu_in_construction; /*!< \brief Memory area where a complete SDU is reassemblied before being send to upper layers. */
|
||||
} rlc_tm_entity_t;
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_TM_MODULE 1
|
||||
#define RLC_TM_INIT_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_tm.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
void config_req_rlc_tm (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_tm_info_t * const config_tmP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP
|
||||
)
|
||||
{
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
rlc_tm_entity_t *rlc_p = NULL;
|
||||
hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
hashtable_rc_t h_rc;
|
||||
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
rlc_p = &rlc_union_p->rlc.tm;
|
||||
LOG_D(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ (is_uplink_downlink=%d) RB %ld\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
|
||||
config_tmP->is_uplink_downlink,
|
||||
rb_idP);
|
||||
|
||||
rlc_tm_init(ctxt_pP, rlc_p);
|
||||
rlc_p->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
|
||||
rlc_tm_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
|
||||
rlc_tm_configure(ctxt_pP, rlc_p, config_tmP->is_uplink_downlink);
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_TM_CTXT_FMT" CONFIG_REQ RB %ld RLC NOT FOUND\n",
|
||||
PROTOCOL_RLC_TM_CTXT_ARGS(ctxt_pP, rlc_p),
|
||||
rb_idP);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_tm_init (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP
|
||||
)
|
||||
{
|
||||
int saved_allocation = rlcP->allocation;
|
||||
memset (rlcP, 0, sizeof (struct rlc_tm_entity));
|
||||
rlcP->allocation = saved_allocation;
|
||||
// TX SIDE
|
||||
list_init (&rlcP->pdus_to_mac_layer, NULL);
|
||||
|
||||
rlcP->protocol_state = RLC_NULL_STATE;
|
||||
rlcP->nb_sdu = 0;
|
||||
rlcP->next_sdu_index = 0;
|
||||
rlcP->current_sdu_index = 0;
|
||||
|
||||
rlcP->output_sdu_size_to_write = 0;
|
||||
rlcP->buffer_occupancy = 0;
|
||||
|
||||
// SPARE : not 3GPP
|
||||
rlcP->size_input_sdus_buffer = 16;
|
||||
|
||||
if ((rlcP->input_sdus_alloc == NULL) && (rlcP->size_input_sdus_buffer > 0)) {
|
||||
rlcP->input_sdus_alloc = get_free_mem_block (rlcP->size_input_sdus_buffer * sizeof (void *), __func__);
|
||||
if(rlcP->input_sdus_alloc == NULL) return;
|
||||
rlcP->input_sdus = (mem_block_t **) (rlcP->input_sdus_alloc->data);
|
||||
memset (rlcP->input_sdus, 0, rlcP->size_input_sdus_buffer * sizeof (void *));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_reset_state_variables (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
struct rlc_tm_entity * const rlcP
|
||||
)
|
||||
{
|
||||
rlcP->output_sdu_size_to_write = 0;
|
||||
rlcP->buffer_occupancy = 0;
|
||||
rlcP->nb_sdu = 0;
|
||||
rlcP->next_sdu_index = 0;
|
||||
rlcP->current_sdu_index = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_tm_cleanup (
|
||||
rlc_tm_entity_t * const rlcP
|
||||
)
|
||||
{
|
||||
int index;
|
||||
// TX SIDE
|
||||
list_free (&rlcP->pdus_to_mac_layer);
|
||||
|
||||
if (rlcP->input_sdus_alloc) {
|
||||
for (index = 0; index < rlcP->size_input_sdus_buffer; index++) {
|
||||
if (rlcP->input_sdus[index]) {
|
||||
free_mem_block (rlcP->input_sdus[index], __func__);
|
||||
}
|
||||
}
|
||||
|
||||
free_mem_block (rlcP->input_sdus_alloc, __func__);
|
||||
rlcP->input_sdus_alloc = NULL;
|
||||
}
|
||||
|
||||
// RX SIDE
|
||||
if ((rlcP->output_sdu_in_construction)) {
|
||||
free_mem_block (rlcP->output_sdu_in_construction, __func__);
|
||||
rlcP->output_sdu_in_construction = NULL;
|
||||
}
|
||||
|
||||
memset(rlcP, 0, sizeof(rlc_tm_entity_t));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP,
|
||||
const bool is_uplink_downlinkP)
|
||||
{
|
||||
rlcP->is_uplink_downlink = is_uplink_downlinkP;
|
||||
rlc_tm_reset_state_variables (ctxt_pP, rlcP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_tm_set_debug_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP)
|
||||
{
|
||||
rlcP->rb_id = rb_idP;
|
||||
rlcP->channel_id = chan_idP;
|
||||
|
||||
if (srb_flagP) {
|
||||
rlcP->is_data_plane = 0;
|
||||
} else {
|
||||
rlcP->is_data_plane = 1;
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_tm_init.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the control primitives and initialization.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_tm_init_impl_ RLC TM Init Reference Implementation
|
||||
* @ingroup _rlc_tm_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_TM_INIT_H__
|
||||
# define __RLC_TM_INIT_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "rlc_tm_entity.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_tm_structs.h"
|
||||
//# include "rlc.h"
|
||||
# include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef volatile struct rlc_tm_info_s {
|
||||
uint8_t is_uplink_downlink;
|
||||
} rlc_tm_info_t;
|
||||
|
||||
|
||||
/*! \fn void config_req_rlc_tm (void config_req_rlc_tm (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_tm_info_t * const config_tmP,
|
||||
const rb_id_t rb_idP,
|
||||
const srb_flag_t srb_flagP)
|
||||
* \brief Allocate memory for RLC TM instance, reset protocol variables, and set protocol parameters.
|
||||
* \param[in] srb_flagP Flag to indicate SRB (1) or DRB (0)
|
||||
* \param[in] config_tmP Configuration parameters for RLC TM instance.
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void config_req_rlc_tm (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_tm_info_t * const config_tmP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP);
|
||||
|
||||
/*! \fn void rlc_tm_init (const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP)
|
||||
* \brief Initialize a RLC TM protocol instance, initialize all variables, lists, allocate buffers for making this instance ready to be configured with protocol configuration parameters. After this initialization the RLC TM protocol instance will be in RLC_NULL_STATE state.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
*/
|
||||
void rlc_tm_init (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP);
|
||||
|
||||
/*! \fn void rlc_tm_reset_state_variables (const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP)
|
||||
* \brief Reset protocol variables and state variables to initial values.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
*/
|
||||
void rlc_tm_reset_state_variables(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP);
|
||||
|
||||
/*! \fn void rlc_tm_cleanup(rlc_tm_entity_t * const rlcP)
|
||||
* \brief Free all allocated memory (lists and buffers) previously allocated by this RLC TM instance.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
*/
|
||||
void rlc_tm_cleanup(rlc_tm_entity_t * const rlcP);
|
||||
|
||||
/*! \fn void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP,rlc_tm_entity_t * const rlcP, const bool is_uplink_downlinkP)
|
||||
* \brief Configure RLC TM protocol parameters.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] is_uplink_downlinkP Is this instance is TRANSMITTER_ONLY,
|
||||
RECEIVER_ONLY, or TRANSMITTER_AND_RECEIVER.
|
||||
*/
|
||||
void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP,
|
||||
const bool is_uplink_downlinkP);
|
||||
|
||||
/*! \fn void rlc_tm_set_debug_infos(const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP, const rb_id_t rb_idP, const srb_flag_t srb_flagP)
|
||||
* \brief Set debug informations for a RLC TM protocol instance, these informations are only for trace purpose.
|
||||
* \param[in] rlcP RLC TM protocol instance pointer.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier
|
||||
*/
|
||||
void rlc_tm_set_debug_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_tm_entity_t * const rlcP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP);
|
||||
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_tm_structs.h
|
||||
* \brief This file defines structures used inside the RLC TM.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \company Eurecom
|
||||
* \email: lionel.gauthier@eurecom.fr
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
# ifndef __RLC_TM_STRUCTS_H__
|
||||
# define __RLC_TM_STRUCTS_H__
|
||||
# include "platform_types.h"
|
||||
# include "list.h"
|
||||
# include "mac_primitives.h"
|
||||
# include "rlc_primitives.h"
|
||||
# include "mac_rlc_primitives.h"
|
||||
//-----------------------
|
||||
struct rlc_tm_tx_sdu_management {
|
||||
uint8_t *first_byte;
|
||||
int32_t sdu_creation_time;
|
||||
uint16_t sdu_size;
|
||||
};
|
||||
//-----------------------
|
||||
struct rlc_tm_tx_pdu_management {
|
||||
uint8_t *first_byte;
|
||||
uint8_t dummy[MAC_HEADER_MAX_SIZE];
|
||||
};
|
||||
//-----------------------
|
||||
struct rlc_tm_rx_pdu_management {
|
||||
uint8_t *first_byte;
|
||||
};
|
||||
//-----------------------
|
||||
struct rlc_tm_tx_data_pdu_struct {
|
||||
union {
|
||||
struct rlc_tm_tx_pdu_management tx_pdu_mngmnt;
|
||||
struct mac_tb_req tb_req;
|
||||
struct mac_tx_tb_management tb_mngt;
|
||||
# ifdef BYPASS_L1
|
||||
struct rlc_tm_rx_pdu_management dummy1;
|
||||
struct mac_tb_ind dummy2;
|
||||
struct mac_rx_tb_management dummy3;
|
||||
struct rlc_indication dummy4;
|
||||
# endif
|
||||
} dummy;
|
||||
uint8_t data[1];
|
||||
};
|
||||
//-----------------------
|
||||
struct rlc_tm_data_req_alloc { // alloc enought bytes for sdu mngt also
|
||||
union {
|
||||
struct rlc_tm_data_req dummy1;
|
||||
struct rlc_tm_tx_sdu_management dummy2;
|
||||
} dummy;
|
||||
};
|
||||
# endif
|
||||
@@ -1,12 +0,0 @@
|
||||
#######################################
|
||||
WHAT IS IMPLEMENTED:
|
||||
#######################################
|
||||
All RLC specification 36.322 v9.3.0 concerning UM mode,
|
||||
except:
|
||||
The segmentation and the reception of PDU
|
||||
with a sequence number length of 5 bits.
|
||||
|
||||
#######################################
|
||||
KNOWN BUGS AND LIMITATION:
|
||||
#######################################
|
||||
|
||||
@@ -1,579 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_UM_MODULE 1
|
||||
#define RLC_UM_C 1
|
||||
//-----------------------------------------------------------------------------
|
||||
//#include "rtos_header.h"
|
||||
#include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#if ENABLE_ITTI
|
||||
#include "intertask_interface.h"
|
||||
#endif
|
||||
#include "assertions.h"
|
||||
#include "rlc_um.h"
|
||||
#include "list.h"
|
||||
#include "rlc_primitives.h"
|
||||
#include "mac_primitives.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
#include "rlc_um_very_simple_test.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_um_stat_req (rlc_um_entity_t *rlc_pP,
|
||||
unsigned int *stat_tx_pdcp_sdu,
|
||||
unsigned int *stat_tx_pdcp_bytes,
|
||||
unsigned int *stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int *stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int *stat_tx_data_pdu,
|
||||
unsigned int *stat_tx_data_bytes,
|
||||
unsigned int *stat_rx_pdcp_sdu,
|
||||
unsigned int *stat_rx_pdcp_bytes,
|
||||
unsigned int *stat_rx_data_pdus_duplicate,
|
||||
unsigned int *stat_rx_data_bytes_duplicate,
|
||||
unsigned int *stat_rx_data_pdu,
|
||||
unsigned int *stat_rx_data_bytes,
|
||||
unsigned int *stat_rx_data_pdu_dropped,
|
||||
unsigned int *stat_rx_data_bytes_dropped,
|
||||
unsigned int *stat_rx_data_pdu_out_of_window,
|
||||
unsigned int *stat_rx_data_bytes_out_of_window,
|
||||
unsigned int *stat_timer_reordering_timed_out) {
|
||||
*stat_tx_pdcp_sdu = rlc_pP->stat_tx_pdcp_sdu;
|
||||
*stat_tx_pdcp_bytes = rlc_pP->stat_tx_pdcp_bytes;
|
||||
*stat_tx_pdcp_sdu_discarded = rlc_pP->stat_tx_pdcp_sdu_discarded;
|
||||
*stat_tx_pdcp_bytes_discarded = rlc_pP->stat_tx_pdcp_bytes_discarded;
|
||||
*stat_tx_data_pdu = rlc_pP->stat_tx_data_pdu;
|
||||
*stat_tx_data_bytes = rlc_pP->stat_tx_data_bytes;
|
||||
*stat_rx_pdcp_sdu = rlc_pP->stat_rx_pdcp_sdu;
|
||||
*stat_rx_pdcp_bytes = rlc_pP->stat_rx_pdcp_bytes;
|
||||
*stat_rx_data_pdus_duplicate = rlc_pP->stat_rx_data_pdus_duplicate;
|
||||
*stat_rx_data_bytes_duplicate = rlc_pP->stat_rx_data_bytes_duplicate;
|
||||
*stat_rx_data_pdu = rlc_pP->stat_rx_data_pdu;
|
||||
*stat_rx_data_bytes = rlc_pP->stat_rx_data_bytes;
|
||||
*stat_rx_data_pdu_dropped = rlc_pP->stat_rx_data_pdu_dropped;
|
||||
*stat_rx_data_bytes_dropped = rlc_pP->stat_rx_data_bytes_dropped;
|
||||
*stat_rx_data_pdu_out_of_window = rlc_pP->stat_rx_data_pdu_out_of_window;
|
||||
*stat_rx_data_bytes_out_of_window = rlc_pP->stat_rx_data_bytes_out_of_window;
|
||||
*stat_timer_reordering_timed_out = rlc_pP->stat_timer_reordering_timed_out;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t
|
||||
rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP) {
|
||||
if (rlc_pP->buffer_occupancy > 0) {
|
||||
return rlc_pP->buffer_occupancy;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_get_pdus (const protocol_ctxt_t *const ctxt_pP, void *argP) {
|
||||
rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) argP;
|
||||
|
||||
switch (rlc_p->protocol_state) {
|
||||
case RLC_NULL_STATE:
|
||||
// from 3GPP TS 25.322 V9.2.0 p43
|
||||
// In the NULL state the RLC entity does not exist and therefore it is
|
||||
// not possible to transfer any data through it.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// establishment, the RLC entity:
|
||||
// - is created; and
|
||||
// - enters the DATA_TRANSFER_READY state.
|
||||
break;
|
||||
|
||||
case RLC_DATA_TRANSFER_READY_STATE:
|
||||
|
||||
// from 3GPP TS 25.322 V9.2.0 p43-44
|
||||
// In the DATA_TRANSFER_READY state, unacknowledged mode data can be
|
||||
// exchanged between the entities according to subclause 11.2.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// release, the RLC entity:
|
||||
// -enters the NULL state; and
|
||||
// -is considered as being terminated.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// modification, the RLC entity:
|
||||
// - stays in the DATA_TRANSFER_READY state;
|
||||
// - modifies only the protocol parameters and timers as indicated by
|
||||
// upper layers.
|
||||
// Upon reception of a CRLC-SUSPEND-Req from upper layers, the RLC
|
||||
// entity:
|
||||
// - enters the LOCAL_SUSPEND state.
|
||||
|
||||
// SEND DATA TO MAC
|
||||
if (rlc_p->tx_sn_length == 10) {
|
||||
rlc_um_segment_10 (ctxt_pP, rlc_p);
|
||||
}
|
||||
|
||||
if (rlc_p->tx_sn_length == 5) {
|
||||
rlc_um_segment_5 (ctxt_pP, rlc_p);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case RLC_LOCAL_SUSPEND_STATE:
|
||||
// from 3GPP TS 25.322 V9.2.0 p44
|
||||
// In the LOCAL_SUSPEND state, the RLC entity is suspended, i.e. it does
|
||||
// not send UMD PDUs with "Sequence Number" greater than or equal to a
|
||||
// certain specified value (see subclause 9.7.5).
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// release, the RLC entity:
|
||||
// - enters the NULL state; and
|
||||
// - is considered as being terminated.
|
||||
// Upon reception of a CRLC-RESUME-Req from upper layers, the RLC entity:
|
||||
// - enters the DATA_TRANSFER_READY state; and
|
||||
// - resumes the data transmission.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// modification, the RLC entity:
|
||||
// - stays in the LOCAL_SUSPEND state;
|
||||
// - modifies only the protocol parameters and timers as indicated by
|
||||
// upper layers.
|
||||
// TO DO TAKE CARE OF SN : THE IMPLEMENTATION OF THIS FUNCTIONNALITY IS NOT CRITICAL
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_REQ UNKNOWN PROTOCOL STATE %02X hex\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rlc_p->protocol_state);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_rx (const protocol_ctxt_t *const ctxt_pP, void *argP, struct mac_data_ind data_indP) {
|
||||
rlc_um_entity_t *l_rlc_p = (rlc_um_entity_t *) argP;
|
||||
char message_string[10000];
|
||||
mem_block_t *tb_p;
|
||||
int16_t tb_size_in_bytes;
|
||||
rlc_um_pdu_info_t pdu_info;
|
||||
int index;
|
||||
int octet_index;
|
||||
|
||||
switch (l_rlc_p->protocol_state) {
|
||||
case RLC_NULL_STATE:
|
||||
// from 3GPP TS 25.322 V9.2.0 p43
|
||||
// In the NULL state the RLC entity does not exist and therefore it is
|
||||
// not possible to transfer any data through it.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// establishment, the RLC entity:
|
||||
// - is created; and
|
||||
// - enters the DATA_TRANSFER_READY state.
|
||||
LOG_I(RLC, PROTOCOL_RLC_UM_CTXT_FMT" ERROR MAC_DATA_IND IN RLC_NULL_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p));
|
||||
|
||||
if (data_indP.data.nb_elements > 0) {
|
||||
tb_p = data_indP.data.head;
|
||||
|
||||
while (tb_p != NULL) {
|
||||
tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
|
||||
rlc_um_get_pdu_infos(ctxt_pP,l_rlc_p,(rlc_um_pdu_sn_10_t *) ((struct mac_tb_ind *) (tb_p->data))->data_ptr, tb_size_in_bytes, &pdu_info, l_rlc_p->rx_sn_length);
|
||||
tb_p = tb_p->next;
|
||||
}
|
||||
}
|
||||
|
||||
list_free (&data_indP.data);
|
||||
break;
|
||||
|
||||
case RLC_DATA_TRANSFER_READY_STATE:
|
||||
// from 3GPP TS 25.322 V9.2.0 p43-44
|
||||
// In the DATA_TRANSFER_READY state, unacknowledged mode data can be
|
||||
// exchanged between the entities according to subclause 11.2.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// release, the RLC entity:
|
||||
// -enters the NULL state; and
|
||||
// -is considered as being terminated.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// modification, the RLC entity:
|
||||
// - stays in the DATA_TRANSFER_READY state;
|
||||
// - modifies only the protocol parameters and timers as indicated by
|
||||
// upper layers.
|
||||
// Upon reception of a CRLC-SUSPEND-Req from upper layers, the RLC
|
||||
// entity:
|
||||
// - enters the LOCAL_SUSPEND state.
|
||||
data_indP.tb_size = data_indP.tb_size >> 3;
|
||||
|
||||
if (data_indP.data.nb_elements > 0 && (LOG_DEBUGFLAG(DEBUG_RLC))) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_IND %d TBs\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
data_indP.data.nb_elements);
|
||||
tb_p = data_indP.data.head;
|
||||
|
||||
while (tb_p != NULL) {
|
||||
tb_size_in_bytes = ((struct mac_tb_ind *) (tb_p->data))->size;
|
||||
rlc_um_get_pdu_infos(ctxt_pP,
|
||||
l_rlc_p,(rlc_um_pdu_sn_10_t *) ((struct mac_tb_ind *) (tb_p->data))->data_ptr,
|
||||
tb_size_in_bytes,
|
||||
&pdu_info,
|
||||
l_rlc_p->rx_sn_length);
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
message_string_size = 0;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", tb_size_in_bytes);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC UM DATA IND: UMD PDU\n\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " FI : %u\n", pdu_info.fi);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E : %u\n", pdu_info.e);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SN : %u\n", pdu_info.sn);
|
||||
|
||||
if (pdu_info.e) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension : \n");
|
||||
|
||||
for (index=0; index < pdu_info.num_li; index++) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LI : %u\n", pdu_info.li_list[index]);
|
||||
}
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
LOG_UI(RLC, "%s|\n", message_string);
|
||||
}
|
||||
|
||||
tb_p = tb_p->next;
|
||||
}
|
||||
}
|
||||
|
||||
rlc_um_receive (ctxt_pP, l_rlc_p, data_indP);
|
||||
break;
|
||||
|
||||
case RLC_LOCAL_SUSPEND_STATE:
|
||||
// from 3GPP TS 25.322 V9.2.0 p44
|
||||
// In the LOCAL_SUSPEND state, the RLC entity is suspended, i.e. it does
|
||||
// not send UMD PDUs with "Sequence Number" greater than or equal to a
|
||||
// certain specified value (see subclause 9.7.5).
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// release, the RLC entity:
|
||||
// - enters the NULL state; and
|
||||
// - is considered as being terminated.
|
||||
// Upon reception of a CRLC-RESUME-Req from upper layers, the RLC entity:
|
||||
// - enters the DATA_TRANSFER_READY state; and
|
||||
// - resumes the data transmission.
|
||||
// Upon reception of a CRLC-CONFIG-Req from upper layer indicating
|
||||
// modification, the RLC entity:
|
||||
// - stays in the LOCAL_SUSPEND state;
|
||||
// - modifies only the protocol parameters and timers as indicated by
|
||||
// upper layers.
|
||||
LOG_I(RLC, PROTOCOL_RLC_UM_CTXT_FMT" RLC_LOCAL_SUSPEND_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p));
|
||||
list_free (&data_indP.data);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" TX UNKNOWN PROTOCOL STATE %02X hex\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
l_rlc_p->protocol_state);
|
||||
list_free (&data_indP.data);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_status_resp
|
||||
rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) {
|
||||
struct mac_status_resp status_resp;
|
||||
uint16_t sdu_size = 0;
|
||||
uint16_t sdu_remaining_size = 0;
|
||||
int32_t diff_time=0;
|
||||
rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) rlc_pP;
|
||||
mem_block_t *mb_p = NULL;
|
||||
status_resp.buffer_occupancy_in_pdus = 0;
|
||||
status_resp.buffer_occupancy_in_bytes = 0;
|
||||
status_resp.head_sdu_remaining_size_to_send = 0;
|
||||
status_resp.head_sdu_creation_time = 0;
|
||||
status_resp.head_sdu_is_segmented = 0;
|
||||
|
||||
if (rlc_pP) {
|
||||
status_resp.rlc_info.rlc_protocol_state = rlc_p->protocol_state;
|
||||
rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_p);
|
||||
status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p);
|
||||
|
||||
if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
|
||||
if (enb_flagP == ENB_FLAG_YES) {
|
||||
/* For eNB: add minimum RLC UM header size for the scheduler */
|
||||
/* For UE : RLC header part is not taken into account for BSR reporting (cf 36.321) */
|
||||
status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
|
||||
}
|
||||
|
||||
status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements;
|
||||
diff_time = ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time;
|
||||
status_resp.head_sdu_creation_time = (diff_time > 0 ) ? (uint32_t) diff_time : (uint32_t)(0xffffffff - diff_time + ctxt_pP->frame) ;
|
||||
//msg("rlc_p status for ctxt_pP->frame %d diff time %d resp %d\n", ctxt_pP->frame, diff_time,status_resp.head_sdu_creation_time) ;
|
||||
sdu_size = ((struct rlc_um_tx_sdu_management *) mb_p->data)->sdu_size;
|
||||
sdu_remaining_size = ((struct rlc_um_tx_sdu_management *) mb_p->data)->sdu_remaining_size;
|
||||
status_resp.head_sdu_remaining_size_to_send = sdu_remaining_size;
|
||||
|
||||
if (sdu_size == sdu_remaining_size) {
|
||||
status_resp.head_sdu_is_segmented = 0;
|
||||
} else {
|
||||
status_resp.head_sdu_is_segmented = 1;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
status_resp.rlc_info.rlc_protocol_state = rlc_p->protocol_state;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC)) {
|
||||
if (( rlc_p->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) {
|
||||
LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT"MAC_STATUS_INDICATION (DATA) -> %d bytes available\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
status_resp.buffer_occupancy_in_bytes);
|
||||
|
||||
if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_STATUS_INDICATION TX STATUS SUCCESSFUL %d PDUs\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
tx_statusP.no_pdu);
|
||||
}
|
||||
|
||||
if ((tx_statusP.tx_status == MAC_TX_STATUS_UNSUCCESSFUL) && (tx_statusP.no_pdu)) {
|
||||
LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_STATUS_INDICATION TX STATUS UNSUCCESSFUL %d PDUs\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
tx_statusP.no_pdu);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, "[RLC] rlc_um_mac_status_indication RLC NULL!!!\n");
|
||||
}
|
||||
|
||||
return status_resp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
struct mac_data_req
|
||||
rlc_um_mac_data_request (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP,const eNB_flag_t enb_flagP) {
|
||||
struct mac_data_req data_req;
|
||||
int16_t tb_size_in_bytes;
|
||||
mem_block_t *tb_p;
|
||||
char message_string[10000];
|
||||
size_t message_string_size = 0;
|
||||
rlc_um_pdu_info_t pdu_info;
|
||||
int octet_index, index;
|
||||
rlc_um_entity_t *l_rlc_p = (rlc_um_entity_t *) rlc_pP;
|
||||
rlc_um_get_pdus(ctxt_pP, l_rlc_p);
|
||||
list_init (&data_req.data, NULL);
|
||||
list_add_list (&l_rlc_p->pdus_to_mac_layer, &data_req.data);
|
||||
|
||||
if (enb_flagP) {
|
||||
// redundant in UE MAC Tx processing and not used in eNB scheduler ...
|
||||
data_req.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (l_rlc_p);
|
||||
|
||||
if (data_req.buffer_occupancy_in_bytes > 0) {
|
||||
data_req.buffer_occupancy_in_bytes += l_rlc_p->tx_header_min_length_in_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
data_req.rlc_info.rlc_protocol_state = l_rlc_p->protocol_state;
|
||||
|
||||
if (data_req.data.nb_elements > 0) {
|
||||
tb_p = data_req.data.head;
|
||||
|
||||
while (tb_p != NULL) {
|
||||
tb_size_in_bytes = ((struct mac_tb_req *) (tb_p->data))->tb_size;
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" MAC_DATA_REQUEST TB SIZE %u\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,l_rlc_p),
|
||||
((struct mac_tb_req *) (tb_p->data))->tb_size);
|
||||
l_rlc_p->stat_tx_data_pdu += 1;
|
||||
l_rlc_p->stat_tx_data_bytes += tb_size_in_bytes;
|
||||
|
||||
//AssertFatal( tb_size_in_bytes > 0 , "RLC UM PDU LENGTH %d", tb_size_in_bytes);
|
||||
if(tb_size_in_bytes <= 0) {
|
||||
LOG_E(RLC, "RLC UM PDU LENGTH %d\n", tb_size_in_bytes);
|
||||
tb_p = tb_p->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC) ) {
|
||||
rlc_um_get_pdu_infos(ctxt_pP, l_rlc_p,(rlc_um_pdu_sn_10_t *) ((struct mac_tb_req *) (tb_p->data))->data_ptr, tb_size_in_bytes, &pdu_info, l_rlc_p->rx_sn_length);
|
||||
|
||||
message_string_size = 0;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", l_rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU size : %u\n", tb_size_in_bytes);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header size : %u\n", pdu_info.header_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Payload size: %u\n", pdu_info.payload_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "PDU type : RLC UM DATA IND: UMD PDU\n\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Header :\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " FI : %u\n", pdu_info.fi);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " E : %u\n", pdu_info.e);
|
||||
message_string_size += sprintf(&message_string[message_string_size], " SN : %u\n", pdu_info.sn);
|
||||
|
||||
if (pdu_info.e) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nHeader extension : \n");
|
||||
|
||||
for (index=0; index < pdu_info.num_li; index++) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " LI : %u\n", pdu_info.li_list[index]);
|
||||
}
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < pdu_info.payload_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", pdu_info.payload[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
LOG_UI(RLC, "%s\n", message_string);
|
||||
} /* LOG_DEBUGFLAG(DEBUG_RLC) */
|
||||
|
||||
tb_p = tb_p->next;
|
||||
} /* while (tb_p != NULL) */
|
||||
} /* if (data_req.data.nb_elements > 0) */
|
||||
|
||||
data_req.buffer_occupancy_in_pdus = 0;
|
||||
return data_req;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_mac_data_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, struct mac_data_ind data_indP) {
|
||||
rlc_um_rx (ctxt_pP, rlc_pP, data_indP);
|
||||
rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_pP);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_data_req (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, mem_block_t *sdu_pP) {
|
||||
rlc_um_entity_t *rlc_p = (rlc_um_entity_t *) rlc_pP;
|
||||
uint16_t data_offset;
|
||||
uint16_t data_size;
|
||||
size_t message_string_size = 0;
|
||||
int octet_index, index;
|
||||
char message_string[7000];
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" RLC_UM_DATA_REQ size %d Bytes, BO %d , NB SDU %d\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
((struct rlc_um_data_req *) (sdu_pP->data))->data_size,
|
||||
rlc_p->buffer_occupancy,
|
||||
rlc_p->input_sdus.nb_elements);
|
||||
// IMPORTANT : do not change order of affectations
|
||||
((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size = ((struct rlc_um_data_req *) (sdu_pP->data))->data_size;
|
||||
//rlc_p->nb_sdu += 1;
|
||||
((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->first_byte = (uint8_t *)&sdu_pP->data[sizeof (struct rlc_um_data_req_alloc)];
|
||||
((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_remaining_size = ((struct rlc_um_tx_sdu_management *)
|
||||
(sdu_pP->data))->sdu_size;
|
||||
((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_segmented_size = 0;
|
||||
((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_creation_time = ctxt_pP->frame;
|
||||
//rlc_p->next_sdu_index = (rlc_p->next_sdu_index + 1) % rlc_p->size_input_sdus_buffer;
|
||||
rlc_p->stat_tx_pdcp_sdu += 1;
|
||||
rlc_p->stat_tx_pdcp_bytes += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_RLC) ) {
|
||||
data_offset = sizeof (struct rlc_um_data_req_alloc);
|
||||
data_size = ((struct rlc_um_tx_sdu_management *)(sdu_pP->data))->sdu_size;
|
||||
message_string_size += sprintf(&message_string[message_string_size], "Bearer : %ld\n", rlc_p->rb_id);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "SDU size : %u\n", data_size);
|
||||
message_string_size += sprintf(&message_string[message_string_size], "\nPayload : \n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], " | 0 1 2 3 4 5 6 7 8 9 a b c d e f |\n");
|
||||
message_string_size += sprintf(&message_string[message_string_size], "------+-------------------------------------------------|\n");
|
||||
|
||||
for (octet_index = 0; octet_index < data_size; octet_index++) {
|
||||
if ((octet_index % 16) == 0) {
|
||||
if (octet_index != 0) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " |\n");
|
||||
}
|
||||
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %04d |", octet_index);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print every single octet in hexadecimal form
|
||||
*/
|
||||
message_string_size += sprintf(&message_string[message_string_size], " %02x", ((uint8_t *)(&sdu_pP->data[data_offset]))[octet_index]);
|
||||
/*
|
||||
* Align newline and pipes according to the octets in groups of 2
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Append enough spaces and put final pipe
|
||||
*/
|
||||
for (index = octet_index; index < 16; ++index) {
|
||||
message_string_size += sprintf(&message_string[message_string_size], " ");
|
||||
}
|
||||
|
||||
LOG_UI(RLC, "%s|\n", message_string);
|
||||
}
|
||||
|
||||
RLC_UM_MUTEX_LOCK(&rlc_p->lock_input_sdus, ctxt_pP, rlc_p);
|
||||
rlc_p->buffer_occupancy += ((struct rlc_um_tx_sdu_management *) (sdu_pP->data))->sdu_size;
|
||||
list_add_tail_eurecom(sdu_pP, &rlc_p->input_sdus);
|
||||
RLC_UM_MUTEX_UNLOCK(&rlc_p->lock_input_sdus);
|
||||
|
||||
LOG_T(RLC, PROTOCOL_RLC_UM_CTXT_FMT" BO %d , NB SDU %d\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rlc_p->buffer_occupancy,
|
||||
rlc_p->input_sdus.nb_elements);
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um.h
|
||||
* \brief This file, and only this file must be included by code that interact with RLC UM layer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_um_impl_ RLC UM Layer Reference Implementation
|
||||
* @ingroup _rlc_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_H__
|
||||
# define __RLC_UM_H__
|
||||
# include <errno.h>
|
||||
# include "platform_types.h"
|
||||
# include "rlc_def.h"
|
||||
# include "rlc_def_lte.h"
|
||||
# include "rlc_um_constants.h"
|
||||
# include "rlc_um_structs.h"
|
||||
# include "rlc_um_entity.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_um_control_primitives.h"
|
||||
# include "rlc_um_dar.h"
|
||||
# include "rlc_um_fsm.h"
|
||||
# include "rlc_um_reassembly.h"
|
||||
# include "rlc_um_receiver.h"
|
||||
# include "rlc_um_segment.h"
|
||||
# include "rlc_um_test.h"
|
||||
|
||||
#define PROTOCOL_RLC_UM_CTXT_FMT PROTOCOL_CTXT_FMT"[%s %02ld] %s()"
|
||||
#define PROTOCOL_RLC_UM_CTXT_ARGS(CTXT_Pp, rLC_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp),\
|
||||
(rLC_Pp->is_data_plane) ? "DRB UM" : "SRB UM",\
|
||||
rLC_Pp->rb_id,\
|
||||
__FUNCTION__
|
||||
|
||||
#if defined(TRACE_RLC_MUTEX)
|
||||
#define RLC_UM_MUTEX_LOCK(mUTEX, cTXT, rLC) \
|
||||
do {\
|
||||
int pmtl_rc = pthread_mutex_trylock(mUTEX);\
|
||||
if (pmtl_rc != 0){\
|
||||
if (pmtl_rc == EBUSY) {\
|
||||
pthread_mutex_lock(mUTEX);\
|
||||
}\
|
||||
}\
|
||||
} while (0);
|
||||
#else
|
||||
#define RLC_UM_MUTEX_LOCK(mUTEX, cTXT, rLC) pthread_mutex_lock(mUTEX)
|
||||
#endif
|
||||
|
||||
#define RLC_UM_MUTEX_UNLOCK(mUTEX) pthread_mutex_unlock(mUTEX)
|
||||
|
||||
/*! \fn void rlc_um_stat_req (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,
|
||||
unsigned int* stat_tx_pdcp_sdu,
|
||||
unsigned int* stat_tx_pdcp_bytes,
|
||||
unsigned int* stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int* stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int* stat_tx_data_pdu,
|
||||
unsigned int* stat_tx_data_bytes,
|
||||
unsigned int* stat_rx_pdcp_sdu,
|
||||
unsigned int* stat_rx_pdcp_bytes,
|
||||
unsigned int* stat_rx_data_pdus_duplicate,
|
||||
unsigned int* stat_rx_data_bytes_duplicate,
|
||||
unsigned int* stat_rx_data_pdu,
|
||||
unsigned int* stat_rx_data_bytes,
|
||||
unsigned int* stat_rx_data_pdu_dropped,
|
||||
unsigned int* stat_rx_data_bytes_dropped,
|
||||
unsigned int* stat_rx_data_pdu_out_of_window,
|
||||
unsigned int* stat_rx_data_bytes_out_of_window,
|
||||
unsigned int* stat_timer_reordering_timed_out)
|
||||
* \brief Request TX and RX statistics of a RLC AM protocol instance.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[out] stat_tx_pdcp_sdu Number of SDUs coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_bytes Number of bytes coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_sdu_discarded Number of discarded SDUs coming from upper layers.
|
||||
* \param[out] stat_tx_pdcp_bytes_discarded Number of discarded bytes coming from upper layers.
|
||||
* \param[out] stat_tx_data_pdu Number of transmitted data PDUs to lower layers.
|
||||
* \param[out] stat_tx_data_bytes Number of transmitted data bytes to lower layers.
|
||||
* \param[out] stat_rx_pdcp_sdu Number of SDUs delivered to upper layers.
|
||||
* \param[out] stat_rx_pdcp_bytes Number of bytes delivered to upper layers.
|
||||
* \param[out] stat_rx_data_pdus_duplicate Number of duplicate PDUs received.
|
||||
* \param[out] stat_rx_data_bytes_duplicate Number of duplicate bytes received.
|
||||
* \param[out] stat_rx_data_pdu Number of received PDUs from lower layers.
|
||||
* \param[out] stat_rx_data_bytes Number of received bytes from lower layers.
|
||||
* \param[out] stat_rx_data_pdu_dropped Number of received PDUs from lower layers, then dropped.
|
||||
* \param[out] stat_rx_data_bytes_dropped Number of received bytes from lower layers, then dropped.
|
||||
* \param[out] stat_rx_data_pdu_out_of_window Number of data PDUs received out of the receive window.
|
||||
* \param[out] stat_rx_data_bytes_out_of_window Number of data bytes received out of the receive window.
|
||||
* \param[out] stat_timer_reordering_timed_out Number of times the timer "reordering" has timed-out.
|
||||
*/
|
||||
void rlc_um_stat_req (rlc_um_entity_t *rlc_pP,
|
||||
unsigned int* stat_tx_pdcp_sdu,
|
||||
unsigned int* stat_tx_pdcp_bytes,
|
||||
unsigned int* stat_tx_pdcp_sdu_discarded,
|
||||
unsigned int* stat_tx_pdcp_bytes_discarded,
|
||||
unsigned int* stat_tx_data_pdu,
|
||||
unsigned int* stat_tx_data_bytes,
|
||||
unsigned int* stat_rx_pdcp_sdu,
|
||||
unsigned int* stat_rx_pdcp_bytes,
|
||||
unsigned int* stat_rx_data_pdus_duplicate,
|
||||
unsigned int* stat_rx_data_bytes_duplicate,
|
||||
unsigned int* stat_rx_data_pdu,
|
||||
unsigned int* stat_rx_data_bytes,
|
||||
unsigned int* stat_rx_data_pdu_dropped,
|
||||
unsigned int* stat_rx_data_bytes_dropped,
|
||||
unsigned int* stat_rx_data_pdu_out_of_window,
|
||||
unsigned int* stat_rx_data_bytes_out_of_window,
|
||||
unsigned int* stat_timer_reordering_timed_out);
|
||||
|
||||
/*! \fn void rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Request the segmentation of SDUs based on status previously sent by MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void
|
||||
rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, void *argP);
|
||||
/*! \fn void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_data_ind data_indication)
|
||||
* \brief Process the received PDUs from lower layer.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] data_indication PDUs from MAC.
|
||||
*/
|
||||
void
|
||||
rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind data_indP);
|
||||
/*! \fn struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_status_ind tx_statusP)
|
||||
* \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU.
|
||||
* \return The maximum number of bytes that can be served by RLC instance to MAC.
|
||||
*/
|
||||
struct mac_status_resp
|
||||
rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP);
|
||||
|
||||
/*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,const eNB_flag_t enb_flagP)
|
||||
* \brief Gives PDUs to lower layer MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] enb_flagP eNB or UE flag.
|
||||
* \return A PDU of the previously requested number of bytes, and the updated maximum number of bytes that can be served by RLC instance to MAC for next RLC transmission.
|
||||
*/
|
||||
struct mac_data_req
|
||||
rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP,const eNB_flag_t enb_flagP);
|
||||
|
||||
/*! \fn void rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,struct mac_data_ind data_indP)
|
||||
* \brief Receive PDUs from lower layer MAC.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] data_indP PDUs from MAC.
|
||||
*/
|
||||
|
||||
/*! \fn uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP)
|
||||
* \brief Gets Tx Buffer Occupancy.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.)
|
||||
*/
|
||||
uint32_t rlc_um_get_buffer_occupancy (rlc_um_entity_t *rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_data_req (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, mem_block_t *sduP)
|
||||
* \brief Interface with higher layers, buffer higher layer SDUS for transmission.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] sduP SDU. (A struct rlc_um_data_req is mapped on sduP->data.)
|
||||
*/
|
||||
void
|
||||
rlc_um_mac_data_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_data_ind data_indP);
|
||||
void
|
||||
rlc_um_data_req (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, mem_block_t *sdu_pP) ;
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_constants.h
|
||||
* \brief This file defines constant values used inside RLC UM.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/**
|
||||
* @addtogroup _rlc_um_internal_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_CONSTANTS_H__
|
||||
# define __RLC_UM_CONSTANTS_H__
|
||||
|
||||
/** The sequence numbering modulo (10 bits). */
|
||||
# define RLC_UM_SN_10_BITS_MODULO 1024
|
||||
/** The sequence numbering binary mask (10 bits). */
|
||||
# define RLC_UM_SN_10_BITS_MASK 0x03FF
|
||||
/** UM_Window_Size = 512 when a 10 bit SN is configured. */
|
||||
# define RLC_UM_WINDOW_SIZE_SN_10_BITS 512
|
||||
/** The sequence numbering modulo (5 bits). */
|
||||
# define RLC_UM_SN_5_BITS_MODULO 32
|
||||
/** The sequence numbering binary mask (5 bits). */
|
||||
# define RLC_UM_SN_5_BITS_MASK 0x1F
|
||||
/** UM_Window_Size = 16 when a 5 bit SN is configured. */
|
||||
# define RLC_UM_WINDOW_SIZE_SN_5_BITS 16
|
||||
// This constant is used by the receiving UM RLC entity to define SNs of those
|
||||
// UMD PDUs that can be received without causing an advancement of the
|
||||
// receiving window. UM_Window_Size = 16 when a 5 bit SN is configured,
|
||||
// UM_Window_Size = 512 when a 10 bit SN is configured and UM_Window_Size = 0
|
||||
// when the receiving UM RLC entity is configured for MCCH or MTCH.
|
||||
// li field (values shifted 1 bit left)
|
||||
# define RLC_UM_SEGMENT_NB_MAX_LI_PER_PDU 128
|
||||
//----------------------------------------------------------
|
||||
// Events defined for state model of the acknowledged mode entity
|
||||
/** Internal event defined for state model of the RLC UM. */
|
||||
# define RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_NULL_STATE_EVENT 0x00
|
||||
|
||||
/** Internal event defined for state model of the RLC UM. */
|
||||
# define RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT 0x01
|
||||
|
||||
/** Internal event defined for state model of the RLC UM. */
|
||||
# define RLC_UM_RECEIVE_CRLC_SUSPEND_REQ_EVENT 0x10
|
||||
|
||||
/** Internal event defined for state model of the RLC UM. */
|
||||
# define RLC_UM_TRANSMIT_CRLC_SUSPEND_CNF_EVENT 0x11
|
||||
|
||||
/** Internal event defined for state model of the RLC UM. */
|
||||
# define RLC_UM_RECEIVE_CRLC_RESUME_REQ_EVENT 0x12
|
||||
|
||||
/** Marker in RX buffer meaning that a PDU has been received. */
|
||||
# define RLC_UM_PDU_PREVIOUSLY_RECEIVED 0x01
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,392 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_UM_MODULE 1
|
||||
#define RLC_UM_CONTROL_PRIMITIVES_C 1
|
||||
#include "platform_types.h"
|
||||
#include "assertions.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_um.h"
|
||||
#include "rlc_primitives.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
#include "rlc_um_control_primitives.h"
|
||||
#include "LTE_T-Reordering.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void config_req_rlc_um (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_um_info_t *const config_um_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP) {
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
rlc_um_entity_t *rlc_p = NULL;
|
||||
hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
hashtable_rc_t h_rc;
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
if (h_rc == HASH_TABLE_OK) {
|
||||
rlc_p = &rlc_union_p->rlc.um;
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" CONFIG_REQ timer_reordering=%d sn_field_length=%d is_mXch=%d RB %ld\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
config_um_pP->timer_reordering,
|
||||
config_um_pP->sn_field_length,
|
||||
config_um_pP->is_mXch,
|
||||
rb_idP);
|
||||
rlc_um_init(ctxt_pP, rlc_p);
|
||||
|
||||
if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
|
||||
rlc_um_set_debug_infos(ctxt_pP, rlc_p, srb_flagP, rb_idP, chan_idP);
|
||||
rlc_um_configure(
|
||||
ctxt_pP,
|
||||
rlc_p,
|
||||
config_um_pP->timer_reordering,
|
||||
config_um_pP->sn_field_length,
|
||||
config_um_pP->sn_field_length,
|
||||
config_um_pP->is_mXch);
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" CONFIG_REQ RB %ld RLC UM NOT FOUND\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rb_idP);
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
const uint32_t t_Reordering_tab[32] = {0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,110,120,130,140,150,160,170,180,190,200,1600};
|
||||
|
||||
|
||||
void config_req_rlc_um_asn1 (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t mbms_flagP,
|
||||
const mbms_session_id_t mbms_session_idP,
|
||||
const mbms_service_id_t mbms_service_idP,
|
||||
const LTE_UL_UM_RLC_t *const ul_rlc_pP,
|
||||
const LTE_DL_UM_RLC_t *const dl_rlc_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP,
|
||||
const uint32_t sourceL2Id,
|
||||
const uint32_t destinationL2Id
|
||||
) {
|
||||
uint32_t ul_sn_FieldLength = 0;
|
||||
uint32_t dl_sn_FieldLength = 0;
|
||||
uint32_t t_Reordering = 0;
|
||||
rlc_union_t *rlc_union_p = NULL;
|
||||
rlc_um_entity_t *rlc_p = NULL;
|
||||
hash_key_t key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
hashtable_rc_t h_rc;
|
||||
|
||||
if (mbms_flagP) {
|
||||
//AssertFatal(dl_rlc_pP, "No RLC UM DL config");
|
||||
if(dl_rlc_pP == NULL) {
|
||||
LOG_E(RLC, "No RLC UM DL config\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//AssertFatal(ul_rlc_pP == NULL, "RLC UM UL config present");
|
||||
if(ul_rlc_pP != NULL) {
|
||||
LOG_E(RLC, "RLC UM UL config present\n");
|
||||
return;
|
||||
}
|
||||
|
||||
key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_service_idP, mbms_session_idP);
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
//AssertFatal (h_rc == HASH_TABLE_OK, "RLC NOT FOUND enb id %u rnti %i enb flag %u service id %u, session id %u",
|
||||
// ctxt_pP->module_id,
|
||||
// ctxt_pP->rnti,
|
||||
// ctxt_pP->enb_flag,
|
||||
// mbms_service_idP,
|
||||
// mbms_session_idP);
|
||||
if(h_rc != HASH_TABLE_OK) {
|
||||
LOG_E(RLC, "RLC NOT FOUND enb id %u rnti %i enb flag %u service id %u, session id %u\n",
|
||||
ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_service_idP, mbms_session_idP);
|
||||
return;
|
||||
}
|
||||
|
||||
rlc_p = &rlc_union_p->rlc.um;
|
||||
} else if ((sourceL2Id >0 ) && (destinationL2Id >0)) {
|
||||
key = RLC_COLL_KEY_SOURCE_DEST_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, sourceL2Id, destinationL2Id, srb_flagP);
|
||||
} else {
|
||||
key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
}
|
||||
|
||||
h_rc = hashtable_get(rlc_coll_p, key, (void **)&rlc_union_p);
|
||||
|
||||
//AssertFatal (h_rc == HASH_TABLE_OK, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %u, srb flag %u",
|
||||
// ctxt_pP->module_id,
|
||||
// ctxt_pP->rnti,
|
||||
// ctxt_pP->enb_flag,
|
||||
// rb_idP,
|
||||
// srb_flagP);
|
||||
if(h_rc != HASH_TABLE_OK) {
|
||||
LOG_E(RLC, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %ld, srb flag %u\n",
|
||||
ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
return;
|
||||
}
|
||||
|
||||
rlc_p = &rlc_union_p->rlc.um;
|
||||
//-----------------------------------------------------------------------------
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" CONFIG_REQ timer_reordering=%dms sn_field_length= RB %ld \n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
(dl_rlc_pP && dl_rlc_pP->t_Reordering<31)?t_Reordering_tab[dl_rlc_pP->t_Reordering]:-1,
|
||||
rb_idP);
|
||||
rlc_um_init(ctxt_pP, rlc_p);
|
||||
|
||||
if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
|
||||
rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP, chan_idP);
|
||||
|
||||
if (ul_rlc_pP != NULL) {
|
||||
switch (ul_rlc_pP->sn_FieldLength) {
|
||||
case LTE_SN_FieldLength_size5:
|
||||
ul_sn_FieldLength = 5;
|
||||
break;
|
||||
|
||||
case LTE_SN_FieldLength_size10:
|
||||
ul_sn_FieldLength = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID UL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rlc_p->rb_id,
|
||||
ul_rlc_pP->sn_FieldLength);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (dl_rlc_pP != NULL) {
|
||||
switch (dl_rlc_pP->sn_FieldLength) {
|
||||
case LTE_SN_FieldLength_size5:
|
||||
dl_sn_FieldLength = 5;
|
||||
break;
|
||||
|
||||
case LTE_SN_FieldLength_size10:
|
||||
dl_sn_FieldLength = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID DL sn_FieldLength %ld, RLC NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rlc_p->rb_id,
|
||||
dl_rlc_pP->sn_FieldLength);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dl_rlc_pP->t_Reordering<32) {
|
||||
t_Reordering = t_Reordering_tab[dl_rlc_pP->t_Reordering];
|
||||
} else {
|
||||
LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID T_Reordering %ld, RLC NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
|
||||
rlc_p->rb_id,
|
||||
dl_rlc_pP->t_Reordering);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag > 0) {
|
||||
rlc_um_configure(ctxt_pP,rlc_p,
|
||||
t_Reordering,
|
||||
ul_sn_FieldLength,
|
||||
dl_sn_FieldLength,
|
||||
mbms_flagP);
|
||||
} else {
|
||||
rlc_um_configure(ctxt_pP,rlc_p,
|
||||
t_Reordering,
|
||||
dl_sn_FieldLength,
|
||||
ul_sn_FieldLength,
|
||||
mbms_flagP);
|
||||
}
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_init (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP
|
||||
) {
|
||||
//AssertFatal(rlc_pP, "Bad RLC UM pointer (NULL)");
|
||||
if(rlc_pP == NULL) {
|
||||
LOG_E(RLC, "Bad RLC UM pointer (NULL)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rlc_pP->initialized) {
|
||||
LOG_D(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [INIT] ALREADY DONE, DOING NOTHING\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
} else {
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [INIT] STATE VARIABLES, BUFFERS, LISTS\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
memset (rlc_pP, 0, sizeof (rlc_um_entity_t));
|
||||
// TX SIDE
|
||||
list_init (&rlc_pP->pdus_to_mac_layer, NULL);
|
||||
pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL);
|
||||
list_init (&rlc_pP->input_sdus, NULL);
|
||||
rlc_pP->protocol_state = RLC_NULL_STATE;
|
||||
//rlc_pP->vt_us = 0;
|
||||
// RX SIDE
|
||||
list_init (&rlc_pP->pdus_from_mac_layer, NULL);
|
||||
//rlc_pP->vr_ur = 0;
|
||||
//rlc_pP->vr_ux = 0;
|
||||
//rlc_pP->vr_uh = 0;
|
||||
//rlc_pP->output_sdu_size_to_write = 0;
|
||||
//rlc_pP->output_sdu_in_construction = NULL;
|
||||
rlc_pP->rx_sn_length = 10;
|
||||
rlc_pP->rx_header_min_length_in_bytes = 2;
|
||||
rlc_pP->tx_sn_length = 10;
|
||||
rlc_pP->tx_header_min_length_in_bytes = 2;
|
||||
pthread_mutex_init(&rlc_pP->lock_dar_buffer, NULL);
|
||||
|
||||
if (rlc_pP->dar_buffer == NULL) {
|
||||
rlc_pP->dar_buffer = calloc (1, 1024 * sizeof (void *));
|
||||
}
|
||||
|
||||
rlc_pP->first_pdu = 1;
|
||||
rlc_pP->initialized = true;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_reset_state_variables (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP
|
||||
) {
|
||||
rlc_pP->buffer_occupancy = 0;
|
||||
// TX SIDE
|
||||
rlc_pP->vt_us = 0;
|
||||
// RX SIDE
|
||||
rlc_pP->vr_ur = 0;
|
||||
rlc_pP->vr_ux = 0;
|
||||
rlc_pP->vr_uh = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_cleanup (
|
||||
rlc_um_entity_t *const rlc_pP) {
|
||||
int index;
|
||||
// TX SIDE
|
||||
list_free (&rlc_pP->pdus_to_mac_layer);
|
||||
pthread_mutex_destroy(&rlc_pP->lock_input_sdus);
|
||||
list_free (&rlc_pP->input_sdus);
|
||||
// RX SIDE
|
||||
list_free (&rlc_pP->pdus_from_mac_layer);
|
||||
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
free_mem_block (rlc_pP->output_sdu_in_construction, __func__);
|
||||
rlc_pP->output_sdu_in_construction = NULL;
|
||||
}
|
||||
|
||||
if (rlc_pP->dar_buffer) {
|
||||
for (index = 0; index < 1024; index++) {
|
||||
if (rlc_pP->dar_buffer[index]) {
|
||||
free_mem_block (rlc_pP->dar_buffer[index], __func__);
|
||||
}
|
||||
}
|
||||
|
||||
free (rlc_pP->dar_buffer);
|
||||
rlc_pP->dar_buffer = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&rlc_pP->lock_dar_buffer);
|
||||
memset(rlc_pP, 0, sizeof(rlc_um_entity_t));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_um_configure(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP,
|
||||
const uint32_t timer_reorderingP,
|
||||
const uint32_t rx_sn_field_lengthP,
|
||||
const uint32_t tx_sn_field_lengthP,
|
||||
const uint32_t is_mXchP) {
|
||||
if (rx_sn_field_lengthP == 10) {
|
||||
rlc_pP->rx_sn_length = 10;
|
||||
rlc_pP->rx_sn_modulo = RLC_UM_SN_10_BITS_MODULO;
|
||||
rlc_pP->rx_um_window_size = RLC_UM_WINDOW_SIZE_SN_10_BITS;
|
||||
rlc_pP->rx_header_min_length_in_bytes = 2;
|
||||
} else if (rx_sn_field_lengthP == 5) {
|
||||
rlc_pP->rx_sn_length = 5;
|
||||
rlc_pP->rx_sn_modulo = RLC_UM_SN_5_BITS_MODULO;
|
||||
rlc_pP->rx_um_window_size = RLC_UM_WINDOW_SIZE_SN_5_BITS;
|
||||
rlc_pP->rx_header_min_length_in_bytes = 1;
|
||||
} else if (rx_sn_field_lengthP != 0) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->rb_id,
|
||||
rx_sn_field_lengthP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx_sn_field_lengthP == 10) {
|
||||
rlc_pP->tx_sn_length = 10;
|
||||
rlc_pP->tx_sn_modulo = RLC_UM_SN_10_BITS_MODULO;
|
||||
rlc_pP->tx_um_window_size = RLC_UM_WINDOW_SIZE_SN_10_BITS;
|
||||
rlc_pP->tx_header_min_length_in_bytes = 2;
|
||||
} else if (tx_sn_field_lengthP == 5) {
|
||||
rlc_pP->tx_sn_length = 5;
|
||||
rlc_pP->tx_sn_modulo = RLC_UM_SN_5_BITS_MODULO;
|
||||
rlc_pP->tx_um_window_size = RLC_UM_WINDOW_SIZE_SN_5_BITS;
|
||||
rlc_pP->tx_header_min_length_in_bytes = 1;
|
||||
} else if (tx_sn_field_lengthP != 0) {
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %ld INVALID RX SN LENGTH %d BITS NOT IMPLEMENTED YET, RLC NOT CONFIGURED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->rb_id,
|
||||
tx_sn_field_lengthP);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_mXchP > 0) {
|
||||
rlc_pP->tx_um_window_size = 0;
|
||||
rlc_pP->rx_um_window_size = 0;
|
||||
}
|
||||
|
||||
rlc_pP->is_mxch = is_mXchP;
|
||||
rlc_pP->last_reassemblied_sn = rlc_pP->rx_sn_modulo - 1;
|
||||
rlc_pP->last_reassemblied_missing_sn = rlc_pP->rx_sn_modulo - 1;
|
||||
rlc_pP->reassembly_missing_sn_detected = 0;
|
||||
// timers
|
||||
rlc_um_init_timer_reordering(ctxt_pP,rlc_pP, timer_reorderingP);
|
||||
rlc_pP->first_pdu = 1;
|
||||
rlc_um_reset_state_variables (ctxt_pP,rlc_pP);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void rlc_um_set_debug_infos(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" [SET DEBUG INFOS] rb_id %ld srb_flag %d\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rb_idP,
|
||||
srb_flagP);
|
||||
rlc_pP->rb_id = rb_idP;
|
||||
rlc_pP->channel_id = chan_idP;
|
||||
|
||||
if (srb_flagP) {
|
||||
rlc_pP->is_data_plane = 0;
|
||||
} else {
|
||||
rlc_pP->is_data_plane = 1;
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_control_primitives.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the control primitives and initialization.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_um_init_impl_ RLC UM Init Reference Implementation
|
||||
* @ingroup _rlc_um_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_CONTROL_PRIMITIVES_H__
|
||||
# define __RLC_UM_CONTROL_PRIMITIVES_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "rlc_um_entity.h"
|
||||
# include "mem_block.h"
|
||||
# include "rlc_um_structs.h"
|
||||
# include "rlc_um_constants.h"
|
||||
# include "platform_types.h"
|
||||
# include "LTE_DL-UM-RLC.h"
|
||||
# include "LTE_UL-UM-RLC.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef volatile struct {
|
||||
uint32_t is_uplink_downlink;
|
||||
uint32_t timer_reordering;
|
||||
uint32_t sn_field_length; // 5 or 10
|
||||
uint32_t is_mXch; // boolean, true if configured for MTCH or MCCH
|
||||
} rlc_um_info_t;
|
||||
|
||||
|
||||
/*! \fn void config_req_rlc_um (
|
||||
* const protocol_ctxt_t* const ctxt_pP,
|
||||
* const srb_flag_t srb_flagP,
|
||||
* const rlc_um_info_t * const config_umP,
|
||||
* const rb_id_t rb_idP)
|
||||
* \brief Allocate memory for RLC UM instance, reset protocol variables, and set protocol parameters. After this configuration the RLC UM protocol instance will be in RLC_DATA_TRANSFER_READY_STATE state.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] config_umP Configuration parameters for RLC UM instance.
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void config_req_rlc_um (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rlc_um_info_t *const config_umP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP);
|
||||
|
||||
/*! \fn void config_req_rlc_um_asn1 (
|
||||
* const protocol_ctxt_t* const ctxt_pP,
|
||||
* const srb_flag_t srb_flagP,
|
||||
* const MBMS_flag_t mbms_flagP,
|
||||
* const mbms_session_id_t mbms_session_idP,
|
||||
* const mbms_service_id_t mbms_service_idP,
|
||||
* const UL_UM_RLC_t* const ul_rlc_pP,
|
||||
* const DL_UM_RLC_t* const dl_rlc_pP,
|
||||
* const rb_id_t rb_idP)
|
||||
* \brief Allocate memory for RLC UM instance, reset protocol variables, and set protocol parameters. After this configuration the RLC UM protocol instance will be in RLC_DATA_TRANSFER_READY_STATE state.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] mbms_flagP Flag to indicate if this RLC is configured for MBMS.
|
||||
* \param[in] mbms_session_idP MBMS session id.
|
||||
* \param[in] mbms_service_idP MBMS service id.
|
||||
* \param[in] ul_rlc_pP Configuration parameters for RLC UM UL instance.
|
||||
* \param[in] dl_rlc_pP Configuration parameters for RLC UM DL instance.
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void config_req_rlc_um_asn1 (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const MBMS_flag_t mbms_flagP,
|
||||
const mbms_session_id_t mbms_session_idP,
|
||||
const mbms_service_id_t mbms_service_idP,
|
||||
const LTE_UL_UM_RLC_t *const ul_rlc_pP,
|
||||
const LTE_DL_UM_RLC_t *const dl_rlc_pP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP,
|
||||
const uint32_t sourceL2Id,
|
||||
const uint32_t destinationL2Id
|
||||
);
|
||||
|
||||
/*! \fn void rlc_um_init (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Initialize a RLC UM protocol instance, initialize all variables, lists, allocate buffers for making this instance ready to be configured with protocol configuration parameters. After this initialization the RLC UM protocol instance will be in RLC_NULL_STATE state.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_init (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_reset_state_variables (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Reset protocol variables and state variables to initial values.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_reset_state_variables (
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_cleanup(rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Free all allocated memory (lists and buffers) previously allocated by this RLC UM instance.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_cleanup(
|
||||
rlc_um_entity_t *const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_configure(
|
||||
* const protocol_ctxt_t* const ctxt_pP,
|
||||
* rlc_um_entity_t * const rlc_pP,
|
||||
* const uint32_t timer_reorderingP,
|
||||
* const uint32_t rx_sn_field_lengthP,
|
||||
* const uint32_t tx_sn_field_lengthP,
|
||||
* const uint32_t is_mXchP)
|
||||
* \brief Configure RLC UM protocol parameters.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] timer_reorderingP t-Reordering timer initialization value, units in frameP.
|
||||
* \param[in] rx_sn_field_lengthP Length of the sequence number, 5 or 10 bits in reception.
|
||||
* \param[in] tx_sn_field_lengthP Length of the sequence number, 5 or 10 bits in transmission.
|
||||
* \param[in] is_mXchP Is the radio bearer for MCCH, MTCH.
|
||||
*/
|
||||
void rlc_um_configure(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP,
|
||||
const uint32_t timer_reorderingP,
|
||||
const uint32_t rx_sn_field_lengthP,
|
||||
const uint32_t tx_sn_field_lengthP,
|
||||
const uint32_t is_mXchP);
|
||||
|
||||
/*! \fn void rlc_um_set_debug_infos(
|
||||
* const protocol_ctxt_t* const ctxt_pP,
|
||||
* rlc_um_entity_t * const rlc_pP,
|
||||
* const srb_flag_t srb_flagP,
|
||||
* const rb_id_t rb_idP)
|
||||
* \brief Set debug informations for a RLC UM protocol instance, these informations are only for trace purpose.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] srb_flagP Flag to indicate signalling radio bearer (1) or data radio bearer (0).
|
||||
* \param[in] rb_idP Radio bearer identifier.
|
||||
* \param[in] chan_idP Transport channel identifier.
|
||||
*/
|
||||
void rlc_um_set_debug_infos(
|
||||
const protocol_ctxt_t *const ctxt_pP,
|
||||
rlc_um_entity_t *const rlc_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const logical_chan_id_t chan_idP);
|
||||
/** @} */
|
||||
# endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_dar.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the reassembly buffer.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_um_receiver_impl_ RLC UM Receiver Implementation
|
||||
* @ingroup _rlc_um_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_DAR_H__
|
||||
# define __RLC_UM_DAR_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "rlc_um_entity.h"
|
||||
# include "rlc_um_structs.h"
|
||||
# include "rlc_um_constants.h"
|
||||
# include "list.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn signed int rlc_um_get_pdu_infos(const protocol_ctxt_t* const ctxt_pP,const rlc_um_entity_t * const rlc_pP,rlc_um_pdu_sn_10_t* header_pP, int16_t total_sizeP, rlc_um_pdu_info_t* pdu_info_pP, uint8_t sn_lengthP)
|
||||
* \brief Extract PDU informations (header fields, data size, etc) from the serialized PDU.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer..
|
||||
* \param[in] header_pP RLC UM header PDU pointer.
|
||||
* \param[in] total_sizeP Size of RLC UM PDU.
|
||||
* \param[in] pdu_info_pP Structure containing extracted informations from PDU.
|
||||
* \param[in] sn_lengthP Sequence number length in bits in PDU header (5 or 10).
|
||||
* \return 0 if no error was encountered during the parsing of the PDU, else -1;
|
||||
*/
|
||||
signed int rlc_um_get_pdu_infos(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
const rlc_um_entity_t * const rlc_pP,
|
||||
rlc_um_pdu_sn_10_t * const header_pP,
|
||||
const sdu_size_t total_sizeP,
|
||||
rlc_um_pdu_info_t * const pdu_info_pP,
|
||||
const uint8_t sn_lengthP);
|
||||
|
||||
/*! \fn int rlc_um_read_length_indicators(unsigned char**data_ppP, rlc_um_e_li_t* e_li_pP, unsigned int* li_array_pP, unsigned int *num_li_pP, sdu_size_t *data_size_pP)
|
||||
* \brief Reset protocol variables and state variables to initial values.
|
||||
* \param[in,out] data_ppP Pointer on data payload.
|
||||
* \param[in] e_li_pP Pointer on first LI + e bit in PDU.
|
||||
* \param[in,out] li_array_pP Array containing read LI.
|
||||
* \param[in,out] num_li_pP Pointer on number of LI read.
|
||||
* \param[in,out] data_size_pP Pointer on data size.
|
||||
* \return 0 if no error was encountered during the parsing of the PDU, else -1;
|
||||
*/
|
||||
int rlc_um_read_length_indicators(unsigned char**data_ppP, rlc_um_e_li_t* e_li_pP, unsigned int* li_array_pP, unsigned int *num_li_pP, sdu_size_t *data_size_pP);
|
||||
|
||||
/*! \fn void rlc_um_try_reassembly (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, rlc_sn_t start_snP, rlc_sn_t end_snP)
|
||||
* \brief Try reassembly PDUs from DAR buffer, starting at sequence number snP.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] frameP Frame index.
|
||||
* \param[in] start_snP First PDU to be reassemblied if possible.
|
||||
* \param[in] end_snP Last excluded highest sequence number of PDU to be reassemblied.
|
||||
*/
|
||||
void rlc_um_try_reassembly (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const rlc_sn_t start_snP, const rlc_sn_t end_snP);
|
||||
|
||||
/*! \fn void rlc_um_check_timer_reordering(rlc_um_entity_t * const rlc_pP,frame_t frameP)
|
||||
* \brief Check if timer reordering has timed-out, if so it is stopped and has the status "timed-out".
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] frameP Frame index
|
||||
*/
|
||||
void rlc_um_check_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_stop_and_reset_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Stop and reset the timer reordering.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] frameP Frame index.
|
||||
*/
|
||||
void rlc_um_stop_and_reset_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_start_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
|
||||
* \brief Re-arm (based on RLC UM config parameter) and start timer reordering.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] frameP Frame index.
|
||||
*/
|
||||
void rlc_um_start_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP);
|
||||
|
||||
/*! \fn void rlc_um_init_timer_reordering(rlc_um_entity_t * const rlc_pP, const uint32_t ms_durationP)
|
||||
* \brief Initialize the timer reordering with RLC UM time-out config parameter.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] ms_durationP Duration in milliseconds units.
|
||||
*/
|
||||
void rlc_um_init_timer_reordering(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const uint32_t ms_durationP);
|
||||
|
||||
/*! \fn void rlc_um_check_timer_dar_time_out(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,)
|
||||
* \brief Check if t-Reordering expires and take the appropriate actions as described in 3GPP specifications.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_check_timer_dar_time_out(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP);
|
||||
|
||||
/*! \fn mem_block_t *rlc_um_remove_pdu_from_dar_buffer(rlc_um_entity_t * const rlc_pP, uint16_t snP)
|
||||
* \brief Remove the PDU with sequence number snP from the DAR buffer and return it.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return The PDU stored in the DAR buffer having sequence number snP, else return NULL.
|
||||
*/
|
||||
mem_block_t *rlc_um_remove_pdu_from_dar_buffer(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const uint16_t snP);
|
||||
|
||||
/*! \fn mem_block_t *rlc_um_remove_pdu_from_dar_buffer(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const uint16_t snP)
|
||||
* \brief Get the PDU with sequence number snP from the DAR buffer.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] snP Sequence number.
|
||||
* \return The PDU stored in the DAR buffer having sequence number snP, else return NULL.
|
||||
*/
|
||||
mem_block_t* rlc_um_get_pdu_from_dar_buffer(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const uint16_t snP);
|
||||
|
||||
/*! \fn signed int rlc_um_in_window(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,rlc_sn_t lower_boundP, rlc_sn_t snP, rlc_sn_t higher_boundP)
|
||||
* \brief Compute if the sequence number of a PDU is in a window .
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] lower_boundP Lower bound of a window.
|
||||
* \param[in] snP Sequence number of a theorical PDU.
|
||||
* \param[in] higher_boundP Higher bound of a window.
|
||||
* \return -2 if lower_boundP > sn, -1 if higher_boundP < sn, 0 if lower_boundP < sn < higher_boundP, 1 if lower_boundP == sn, 2 if higher_boundP == sn, 3 if higher_boundP == sn == lower_boundP.
|
||||
*/
|
||||
signed int rlc_um_in_window(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const rlc_sn_t lower_boundP, const rlc_sn_t snP, const rlc_sn_t higher_boundP);
|
||||
|
||||
/*! \fn signed int rlc_um_in_reordering_window(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const rlc_sn_t snP)
|
||||
* \brief Compute if the sequence number of a PDU is in a window .
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] snP Sequence number of a theorical PDU.
|
||||
* \return 0 if snP is in reordering window, else -1.
|
||||
*/
|
||||
signed int rlc_um_in_reordering_window(const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, const rlc_sn_t snP);
|
||||
|
||||
/*! \fn void rlc_um_receive_process_dar (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, mem_block_t *pdu_mem_pP,rlc_um_pdu_sn_10_t * const pdu_pP, const sdu_size_t tb_sizeP)
|
||||
* \brief Apply the DAR process for a PDU: put it in DAR buffer and try to reassembly or discard it.
|
||||
* \param[in] ctxt_pP Running context.
|
||||
* \param[in] rlc_pP RLC UM protocol instance pointer.
|
||||
* \param[in] pdu_mem_pP mem_block_t wrapper for a UM PDU .
|
||||
* \param[in] pdu_pP Pointer on the header of the UM PDU.
|
||||
* \param[in] tb_sizeP Size of the UM PDU.
|
||||
*/
|
||||
void rlc_um_receive_process_dar (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, mem_block_t * pdu_mem_pP,rlc_um_pdu_sn_10_t * const pdu_pP,
|
||||
const sdu_size_t tb_sizeP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_entity.h
|
||||
* \brief This file defines the RLC UM variables stored in a struct called rlc_um_entity_t.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note The rlc_um_entity_t structure store protocol variables, statistic variables, allocation variables, buffers and other miscellaneous variables.
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
# ifndef __RLC_UM_ENTITY_H__
|
||||
# define __RLC_UM_ENTITY_H__
|
||||
|
||||
# include <pthread.h>
|
||||
# include "platform_types.h"
|
||||
#include "common/platform_constants.h"
|
||||
# include "list.h"
|
||||
# include "rlc_primitives.h"
|
||||
# include "rlc_def.h"
|
||||
|
||||
typedef struct rlc_um_timer_s {
|
||||
uint32_t ms_time_out; /*!< \brief When set, indicate the time the timer will time-out. */
|
||||
uint32_t ms_start; /*!< \brief indicate the time the timer has been started. */
|
||||
uint32_t ms_duration; /*!< \brief Configured timer duration in frames. */
|
||||
uint32_t running:1; /*!< \brief The timer is running. */
|
||||
uint32_t timed_out:1; /*!< \brief The timer has timed-out. */
|
||||
uint32_t dummy:30; /*!< \brief Bits not used. */
|
||||
} rlc_um_timer_t ;
|
||||
|
||||
|
||||
/*! \struct rlc_um_entity_s
|
||||
* \brief Structure containing a RLC UM instance protocol variables, statistic variables, allocation variables, buffers and other miscellaneous variables.
|
||||
*/
|
||||
|
||||
typedef struct rlc_um_entity_s {
|
||||
bool initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */
|
||||
bool is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */
|
||||
rlc_protocol_state_t protocol_state; /*!< \brief Protocol state, can be RLC_NULL_STATE, RLC_DATA_TRANSFER_READY_STATE, RLC_LOCAL_SUSPEND_STATE. */
|
||||
bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */
|
||||
bool is_mxch; /*!< \brief To know if the RLC belongs to a MBMS bearer. */
|
||||
//-----------------------------
|
||||
// PROTOCOL VARIABLES
|
||||
//-----------------------------
|
||||
rlc_usn_t
|
||||
vt_us; /*!< \brief This state variable holds the value of the SN to be assigned for the next newly generated UMD PDU. It is initially set to 0, and is updated whenever the UM RLC entity delivers an UMD PDU with SN = VT(US). */
|
||||
rlc_usn_t
|
||||
vr_ur; /*!< \brief UM receive state variable. This state variable holds the value of the SN of the earliest UMD PDU that is still considered for reordering. It is initially set to 0. */
|
||||
rlc_usn_t vr_ux; /*!< \brief UM t-Reordering state variable. This state variable holds the value of the SN following the SN of the UMD PDU which triggered t-Reordering. */
|
||||
rlc_usn_t
|
||||
vr_uh; /*!< \brief UM highest received state variable. This state variable holds the value of the SN following the SN of the UMD PDU with the highest SN among received UMD PDUs, and it serves as the higher edge of the reordering window. It is initially set to 0. */
|
||||
//-----------------------------
|
||||
// TIMERS
|
||||
//-----------------------------
|
||||
struct rlc_um_timer_s t_reordering;
|
||||
//*****************************************************************************
|
||||
// CONFIGURATION PARAMETERS
|
||||
//*****************************************************************************
|
||||
uint8_t tx_sn_length; /*!< \brief Length of sequence number in bits, can be 5 or 10. */
|
||||
uint8_t rx_sn_length; /*!< \brief Length of sequence number in bits, can be 5 or 10. */
|
||||
uint8_t tx_header_min_length_in_bytes; /*!< \brief Length of PDU header, can be 1 or 2 bytes. */
|
||||
uint8_t rx_header_min_length_in_bytes; /*!< \brief Length of PDU header, can be 1 or 2 bytes. */
|
||||
rlc_sn_t tx_sn_modulo; /*!< \brief Module of the sequence number of PDU, can be RLC_UM_SN_5_BITS_MODULO or RLC_UM_SN_10_BITS_MODULO. */
|
||||
rlc_sn_t rx_sn_modulo; /*!< \brief Module of the sequence number of PDU, can be RLC_UM_SN_5_BITS_MODULO or RLC_UM_SN_10_BITS_MODULO. */
|
||||
rlc_sn_t rx_um_window_size;
|
||||
rlc_sn_t tx_um_window_size;
|
||||
//-----------------------------
|
||||
// tranmission
|
||||
//-----------------------------
|
||||
// sdu communication;
|
||||
//pthread_spinlock_t lock_input_sdus;
|
||||
pthread_mutex_t lock_input_sdus;
|
||||
list_t input_sdus; /*!< \brief Input SDU buffer (for SDUs coming from upper layers). Should be accessed as an array. */
|
||||
rlc_buffer_occupancy_t buffer_occupancy; /*!< \brief Number of bytes contained in input_sdus buffer.*/
|
||||
uint32_t nb_bytes_requested_by_mac; /*!< \brief Number of bytes requested by lower layer for next transmission. */
|
||||
list_t pdus_to_mac_layer; /*!< \brief PDUs buffered for transmission to MAC layer. */
|
||||
//*****************************************************************************
|
||||
// RECEIVER
|
||||
//*****************************************************************************
|
||||
mem_block_t *output_sdu_in_construction; /*!< \brief Memory area where a complete SDU is reassemblied before being send to upper layers. */
|
||||
sdu_size_t output_sdu_size_to_write; /*!< \brief Size of the reassemblied SDU. */
|
||||
|
||||
|
||||
//pthread_spinlock_t lock_dar_buffer;
|
||||
pthread_mutex_t lock_dar_buffer;
|
||||
mem_block_t **dar_buffer; /*!< \brief Array of rx PDUs. */
|
||||
list_t pdus_from_mac_layer; /*!< \brief Not Used. */
|
||||
|
||||
logical_chan_id_t channel_id; /*!< \brief Transport channel identifier. */
|
||||
rb_id_t rb_id; /*!< \brief Radio bearer identifier, for statistics and trace purpose. */
|
||||
rlc_usn_t last_reassemblied_sn; /*!< \brief Sequence number of the last reassemblied PDU. */
|
||||
rlc_usn_t last_reassemblied_missing_sn; /*!< \brief Sequence number of the last found missing PDU. */
|
||||
rlc_usn_t reassembly_missing_sn_detected; /*!< \brief Act as a boolean, set if a hole in the sequence numbering of received PDUs has been found. */
|
||||
//-----------------------------
|
||||
// STATISTICS
|
||||
//-----------------------------
|
||||
bool first_pdu; /*!< \brief Act as a boolean, tells if the next PDU is the first PDU to be received. */
|
||||
|
||||
unsigned int stat_tx_pdcp_sdu; /*!< \brief Number of SDUs received from upper layers. */
|
||||
unsigned int stat_tx_pdcp_bytes; /*!< \brief Number of SDU bytes received from upper layers. */
|
||||
unsigned int stat_tx_pdcp_sdu_discarded; /*!< \brief Number of SDUs received from upper layers that have been discarded. */
|
||||
unsigned int stat_tx_pdcp_bytes_discarded; /*!< \brief Number of SDU bytes received from upper layers that have been discarded. */
|
||||
|
||||
unsigned int stat_tx_data_pdu; /*!< \brief For statistic report, number of transmitted PDUs to lower layers. */
|
||||
unsigned int stat_tx_data_bytes; /*!< \brief For statistic report, number of transmitted bytes to lower layers. */
|
||||
unsigned int stat_rx_pdcp_sdu; /*!< \brief For statistic report, number of reassemblied SDUs, sent to upper layers. */
|
||||
unsigned int stat_rx_pdcp_bytes; /*!< \brief For statistic report, number of reassemblied bytes, sent to upper layers. */
|
||||
unsigned int stat_rx_data_pdus_duplicate; /*!< \brief For statistic report, number of received duplicated PDUs from lower layers. */
|
||||
unsigned int stat_rx_data_bytes_duplicate; /*!< \brief For statistic report, number of received duplicated bytes from lower layers. */
|
||||
unsigned int stat_rx_data_pdu; /*!< \brief For statistic report, number of received PDUs from lower layers. */
|
||||
unsigned int stat_rx_data_bytes; /*!< \brief For statistic report, number of received bytes from lower layers. */
|
||||
unsigned int stat_rx_data_pdu_dropped; /*!< \brief For statistic report, number of dropped received PDUs from lower layers. Does not include out of window stat. */
|
||||
unsigned int stat_rx_data_bytes_dropped; /*!< \brief For statistic report, number of dropped received bytes from lower layers. Does not include out of window stat. */
|
||||
unsigned int stat_rx_data_pdu_out_of_window; /*!< \brief Number of data PDUs received out of the receive window. */
|
||||
unsigned int stat_rx_data_bytes_out_of_window; /*!< \brief Number of data bytes received out of the receive window. */
|
||||
unsigned int stat_timer_reordering_timed_out;
|
||||
} rlc_um_entity_t;
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_UM_MODULE 1
|
||||
#define RLC_UM_FSM_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "rlc_um.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
rlc_um_fsm_notify_event (
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
rlc_um_entity_t *rlc_pP, uint8_t eventP)
|
||||
{
|
||||
|
||||
switch (rlc_pP->protocol_state) {
|
||||
//-------------------------------
|
||||
// RLC_NULL_STATE
|
||||
//-------------------------------
|
||||
case RLC_NULL_STATE:
|
||||
switch (eventP) {
|
||||
case RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT:
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM RLC_NULL_STATE -> RLC_DATA_TRANSFER_READY_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
rlc_pP->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM WARNING PROTOCOL ERROR - EVENT %02X hex NOT EXPECTED FROM NULL_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP),
|
||||
eventP);
|
||||
//AssertFatal(1==0,"RLC-UM FSM WARNING PROTOCOL ERROR - EVENT NOT EXPECTED FROM NULL_STATE");
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//-------------------------------
|
||||
// RLC_DATA_TRANSFER_READY_STATE
|
||||
//-------------------------------
|
||||
case RLC_DATA_TRANSFER_READY_STATE:
|
||||
switch (eventP) {
|
||||
case RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_NULL_STATE_EVENT:
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM RLC_DATA_TRANSFER_READY_STATE -> RLC_NULL_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
rlc_pP->protocol_state = RLC_NULL_STATE;
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case RLC_UM_RECEIVE_CRLC_SUSPEND_REQ_EVENT:
|
||||
case RLC_UM_TRANSMIT_CRLC_SUSPEND_CNF_EVENT:
|
||||
LOG_I(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM RLC_DATA_TRANSFER_READY_STATE -> RLC_LOCAL_SUSPEND_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
rlc_pP->protocol_state = RLC_LOCAL_SUSPEND_STATE;
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM WARNING PROTOCOL ERROR - EVENT %02X hex NOT EXPECTED FROM DATA_TRANSFER_READY_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP),
|
||||
eventP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//-------------------------------
|
||||
// RLC_LOCAL_SUSPEND_STATE
|
||||
//-------------------------------
|
||||
case RLC_LOCAL_SUSPEND_STATE:
|
||||
switch (eventP) {
|
||||
case RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_NULL_STATE_EVENT:
|
||||
LOG_I(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM RLC_LOCAL_SUSPEND_STATE -> RLC_NULL_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
rlc_pP->protocol_state = RLC_NULL_STATE;
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case RLC_UM_RECEIVE_CRLC_RESUME_REQ_EVENT:
|
||||
LOG_I(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM RLC_LOCAL_SUSPEND_STATE -> RLC_DATA_TRANSFER_READY_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP));
|
||||
rlc_pP->protocol_state = RLC_DATA_TRANSFER_READY_STATE;
|
||||
return 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM WARNING PROTOCOL ERROR - EVENT %02X hex NOT EXPECTED FROM RLC_LOCAL_SUSPEND_STATE\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP),
|
||||
eventP);
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT" FSM ERROR UNKNOWN STATE %d\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP, rlc_pP),
|
||||
rlc_pP->protocol_state);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_fsm.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the finite state machine of the RLC UM protocol instance.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_um_fsm_impl_ RLC UM FSM Implementation
|
||||
* @ingroup _rlc_um_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_FSM_PROTO_EXTERN_H__
|
||||
# define __RLC_UM_FSM_PROTO_EXTERN_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "platform_types.h"
|
||||
# include "rlc_um_entity.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn int rlc_um_fsm_notify_event (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP, uint8_t eventP)
|
||||
* \brief Send an event to the RLC UM finite state machine.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC UM protocol instance pointer.
|
||||
* \param[in] eventP Event (#RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_NULL_STATE_EVENT,
|
||||
* #RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT,
|
||||
* #RLC_UM_RECEIVE_CRLC_SUSPEND_REQ_EVENT,
|
||||
* #RLC_UM_TRANSMIT_CRLC_SUSPEND_CNF_EVENT,
|
||||
* #RLC_UM_RECEIVE_CRLC_RESUME_REQ_EVENT).
|
||||
* \return 1 if no error was encountered, 0 if the event was not processed.
|
||||
* \Note This FSM is not LTE 9.3.0 compliant, it has to be modified or removed.
|
||||
*/
|
||||
int rlc_um_fsm_notify_event (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP, uint8_t eventP);
|
||||
/** @} */
|
||||
# endif
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define RLC_UM_MODULE 1
|
||||
#define RLC_UM_REASSEMBLY_C 1
|
||||
#include "platform_types.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <string.h>
|
||||
#if ENABLE_ITTI
|
||||
# include "platform_types.h"
|
||||
# include "intertask_interface.h"
|
||||
#endif
|
||||
#include "assertions.h"
|
||||
#include "rlc.h"
|
||||
#include "rlc_um.h"
|
||||
#include "rlc_primitives.h"
|
||||
#include "list.h"
|
||||
#include "LAYER2/MAC/mac_extern.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void
|
||||
rlc_um_clear_rx_sdu (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t* rlc_pP)
|
||||
{
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_reassembly (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *rlc_pP, uint8_t * src_pP, int32_t lengthP)
|
||||
{
|
||||
sdu_size_t sdu_max_size;
|
||||
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[REASSEMBLY] reassembly() %d bytes %d bytes already reassemblied\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
lengthP,
|
||||
rlc_pP->output_sdu_size_to_write);
|
||||
|
||||
if (lengthP <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rlc_pP->is_data_plane)) {
|
||||
sdu_max_size = RLC_SDU_MAX_SIZE_DATA_PLANE;
|
||||
} else {
|
||||
sdu_max_size = RLC_SDU_MAX_SIZE_CONTROL_PLANE;
|
||||
}
|
||||
|
||||
if (rlc_pP->output_sdu_in_construction == NULL) {
|
||||
// msg("[RLC_UM_LITE] Getting mem_block ...\n");
|
||||
rlc_pP->output_sdu_in_construction = get_free_mem_block (sdu_max_size, __func__);
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
// check if no overflow in size
|
||||
if ((rlc_pP->output_sdu_size_to_write + lengthP) <= sdu_max_size) {
|
||||
memcpy (&rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write], src_pP, lengthP);
|
||||
rlc_pP->output_sdu_size_to_write += lengthP;
|
||||
#if TRACE_RLC_UM_DISPLAY_ASCII_DATA
|
||||
rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write] = 0;
|
||||
LOG_T(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[REASSEMBLY] DATA :",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_util_print_hex_octets(RLC, (unsigned char*)rlc_pP->output_sdu_in_construction->data, rlc_pP->output_sdu_size_to_write);
|
||||
#endif
|
||||
} else {
|
||||
#if STOP_ON_IP_TRAFFIC_OVERLOAD
|
||||
AssertFatal(0, PROTOCOL_RLC_UM_CTXT_FMT" RLC_UM_DATA_IND, SDU TOO BIG, DROPPED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[REASSEMBLY] [max_sdu size %d] ERROR SDU SIZE OVERFLOW SDU GARBAGED\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
sdu_max_size);
|
||||
// erase SDU
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[REASSEMBLY]ERROR OUTPUT SDU IS NULL\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#if STOP_ON_IP_TRAFFIC_OVERLOAD
|
||||
AssertFatal(0, PROTOCOL_RLC_UM_CTXT_FMT" RLC_UM_DATA_IND, SDU DROPPED, OUT OF MEMORY\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
rlc_um_send_sdu (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t *rlc_pP)
|
||||
{
|
||||
if ((rlc_pP->output_sdu_in_construction)) {
|
||||
LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT" SEND_SDU to upper layers %d bytes sdu %p\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP),
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
|
||||
if (rlc_pP->output_sdu_size_to_write > 0) {
|
||||
rlc_pP->stat_rx_pdcp_sdu += 1;
|
||||
rlc_pP->stat_rx_pdcp_bytes += rlc_pP->output_sdu_size_to_write;
|
||||
|
||||
#if TEST_RLC_UM
|
||||
#if TRACE_RLC_UM_DISPLAY_ASCII_DATA
|
||||
rlc_pP->output_sdu_in_construction->data[rlc_pP->output_sdu_size_to_write] = 0;
|
||||
LOG_T(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[SEND_SDU] DATA :",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
rlc_util_print_hex_octets(RLC, rlc_pP->output_sdu_in_construction->data, rlc_pP->output_sdu_size_to_write);
|
||||
#endif
|
||||
rlc_um_v9_3_0_test_data_ind (rlc_pP->module_id, rlc_pP->rb_id, rlc_pP->output_sdu_size_to_write, rlc_pP->output_sdu_in_construction);
|
||||
#else
|
||||
// msg("[RLC] DATA IND ON MOD_ID %d RB ID %d, size %d\n",rlc_pP->module_id, rlc_pP->rb_id, ctxt_pP->frame,rlc_pP->output_sdu_size_to_write);
|
||||
rlc_data_ind (
|
||||
ctxt_pP,
|
||||
BOOL_NOT(rlc_pP->is_data_plane),
|
||||
rlc_pP->is_mxch,
|
||||
rlc_pP->rb_id,
|
||||
rlc_pP->output_sdu_size_to_write,
|
||||
rlc_pP->output_sdu_in_construction);
|
||||
#endif
|
||||
rlc_pP->output_sdu_in_construction = NULL;
|
||||
} else {
|
||||
LOG_E(RLC, PROTOCOL_RLC_UM_CTXT_FMT"[SEND_SDU] ERROR SIZE <= 0 ... DO NOTHING, SET SDU SIZE TO 0\n",
|
||||
PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_pP));
|
||||
}
|
||||
|
||||
rlc_pP->output_sdu_size_to_write = 0;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*! \file rlc_um_reassembly.h
|
||||
* \brief This file defines the prototypes of the functions dealing with the reassembly of segments.
|
||||
* \author GAUTHIER Lionel
|
||||
* \date 2010-2011
|
||||
* \version
|
||||
* \note
|
||||
* \bug
|
||||
* \warning
|
||||
*/
|
||||
/** @defgroup _rlc_um_receiver_impl_ RLC UM Receiver Implementation
|
||||
* @ingroup _rlc_um_impl_
|
||||
* @{
|
||||
*/
|
||||
# ifndef __RLC_UM_REASSEMBLY_PROTO_EXTERN_H__
|
||||
# define __RLC_UM_REASSEMBLY_PROTO_EXTERN_H__
|
||||
//-----------------------------------------------------------------------------
|
||||
# include "rlc_um_entity.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! \fn void rlc_um_clear_rx_sdu (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP)
|
||||
* \brief Erase the SDU in construction.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_clear_rx_sdu (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP);
|
||||
|
||||
/*! \fn void rlc_um_reassembly (uint8_t * srcP, int32_t lengthP, rlc_um_entity_t *rlcP, frame_t frame)
|
||||
* \brief Reassembly lengthP bytes to the end of the SDU in construction.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC UM protocol instance pointer.
|
||||
* \param[in] srcP Pointer on data to be reassemblied.
|
||||
* \param[in] lengthP Length to reassembly.
|
||||
*/
|
||||
void rlc_um_reassembly (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP, uint8_t * srcP, int32_t lengthP);
|
||||
|
||||
/*! \fn void rlc_um_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP)
|
||||
* \brief Send SDU if any reassemblied to upper layer.
|
||||
* \param[in] ctxtP Running context.
|
||||
* \param[in] rlcP RLC UM protocol instance pointer.
|
||||
*/
|
||||
void rlc_um_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_um_entity_t *rlcP);
|
||||
/** @} */
|
||||
# endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user