Commit 316f6aba authored by Cedric Roux's avatar Cedric Roux

Merge branch 'develop_integration_w13' into 'develop'

Develop integration w13

Summary of changes:
- RLC AM reworking (a lot has changed)
- several bug fixes
  * support processing multiple MAC RAR control elements in a single MSG2
  * fix ACK/NACK resetting
  * do not correct USRP frequency from carrier offset estimation when --ue-carrier-scan == off
  * fix TDD uplink due to incorrect PUCCH format for SR in TDD
  * several other simple fixes
- better support for LMS SDR

See merge request !168
parents a77082c1 c36c0453
...@@ -33,6 +33,13 @@ ORIGIN_PATH=$PWD ...@@ -33,6 +33,13 @@ ORIGIN_PATH=$PWD
THIS_SCRIPT_PATH=$(dirname $(readlink -f $0)) THIS_SCRIPT_PATH=$(dirname $(readlink -f $0))
source $THIS_SCRIPT_PATH/tools/build_helper source $THIS_SCRIPT_PATH/tools/build_helper
# set environment variables (OPENAIR_HOME, ...)
set_openair_env
#variables for UE data generation
gen_nvram_path=$OPENAIR_DIR/targets/bin
conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf
MSC_GEN="False" MSC_GEN="False"
XFORMS="True" XFORMS="True"
FLEXRAN_AGENT_SB_IF="True" FLEXRAN_AGENT_SB_IF="True"
...@@ -55,11 +62,10 @@ T_TRACER="False" ...@@ -55,11 +62,10 @@ T_TRACER="False"
DISABLE_HARDWARE_DEPENDENCY="False" DISABLE_HARDWARE_DEPENDENCY="False"
CMAKE_BUILD_TYPE="" CMAKE_BUILD_TYPE=""
UE_AUTOTEST_TRACE="False" UE_AUTOTEST_TRACE="False"
BUILD_ECLIPSE=0
CMAKE_CMD='cmake'
trap handle_ctrl_c INT trap handle_ctrl_c INT
gen_nvram_path=$OPENAIR_DIR/targets/bin
conf_nvram_path=$OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf
function print_help() { function print_help() {
echo_info " echo_info "
This program installs OpenAirInterface Software This program installs OpenAirInterface Software
...@@ -141,6 +147,8 @@ Options ...@@ -141,6 +147,8 @@ Options
Disable HW dependency during installation Disable HW dependency during installation
--ue-autotest-trace --ue-autotest-trace
Enable specific traces for UE autotest framework Enable specific traces for UE autotest framework
--build-eclipse
Build eclipse project files. Paths are auto corrected by fixprj.sh
Usage (first build): Usage (first build):
oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files oaisim (eNB + UE): ./build_oai -I --oaisim -x --install-system-files
Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files Eurecom EXMIMO + COTS UE : ./build_oai -I --eNB -x --install-system-files
...@@ -179,6 +187,7 @@ function main() { ...@@ -179,6 +187,7 @@ function main() {
GDB=1 GDB=1
CMAKE_BUILD_TYPE="Debug" CMAKE_BUILD_TYPE="Debug"
echo_info "Will Compile with gdb symbols and disable compiler optimization" echo_info "Will Compile with gdb symbols and disable compiler optimization"
CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug"
shift;; shift;;
--eNB) --eNB)
eNB=1 eNB=1
...@@ -311,6 +320,11 @@ function main() { ...@@ -311,6 +320,11 @@ function main() {
UHD_IMAGES_DIR=$2 UHD_IMAGES_DIR=$2
echo_info "Downloading UHD images in the indicated location" echo_info "Downloading UHD images in the indicated location"
shift 2;; shift 2;;
--build-eclipse)
BUILD_ECLIPSE=1
CMAKE_CMD="$CMAKE_CMD"' -DCMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT=TRUE -G"Eclipse CDT4 - Unix Makefiles"'
echo_info "Enabling build eclipse project support"
shift 1;;
-h | --help) -h | --help)
print_help print_help
exit 1;; exit 1;;
...@@ -321,6 +335,9 @@ function main() { ...@@ -321,6 +335,9 @@ function main() {
esac esac
done done
CMAKE_CMD="$CMAKE_CMD .."
echo_info "CMAKE_CMD=$CMAKE_CMD"
######################################################### #########################################################
# check validity of HW and TP parameters for RRH and eNB # check validity of HW and TP parameters for RRH and eNB
######################################################### #########################################################
...@@ -391,7 +408,6 @@ function main() { ...@@ -391,7 +408,6 @@ function main() {
echo_info "2. Setting the OAI PATHS ..." echo_info "2. Setting the OAI PATHS ..."
set_openair_env
cecho "OPENAIR_DIR = $OPENAIR_DIR" $green cecho "OPENAIR_DIR = $OPENAIR_DIR" $green
# for conf files copy in this bash script # for conf files copy in this bash script
...@@ -495,7 +511,7 @@ function main() { ...@@ -495,7 +511,7 @@ function main() {
fi fi
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$lte_build_dir/build cd $DIR/$lte_build_dir/build
cmake .. eval $CMAKE_CMD
fi fi
if [ "$eNB" = "1" -o "$UE" = "1" ] ; then if [ "$eNB" = "1" -o "$UE" = "1" ] ; then
...@@ -524,7 +540,7 @@ function main() { ...@@ -524,7 +540,7 @@ function main() {
# mkdir -p $DIR/at_commands/build # mkdir -p $DIR/at_commands/build
# cd $DIR/at_commands/build # cd $DIR/at_commands/build
# cmake .. # eval $CMAKE_CMD
# compilations \ # compilations \
# at_commands at_nas_ue \ # at_commands at_nas_ue \
# at_nas_ue $dbin/at_nas_ue # at_nas_ue $dbin/at_nas_ue
...@@ -533,7 +549,7 @@ function main() { ...@@ -533,7 +549,7 @@ function main() {
mkdir -p $DIR/nas_sim_tools/build mkdir -p $DIR/nas_sim_tools/build
cd $DIR/nas_sim_tools/build cd $DIR/nas_sim_tools/build
cmake .. eval $CMAKE_CMD
compilations \ compilations \
nas_sim_tools usim \ nas_sim_tools usim \
usim $dbin/usim usim $dbin/usim
...@@ -562,7 +578,7 @@ function main() { ...@@ -562,7 +578,7 @@ function main() {
mkdir -p build mkdir -p build
cd build cd build
rm -f *sim rm -f *sim
cmake .. eval $CMAKE_CMD
fi fi
if [ "$SIMUS_PHY" = "1" ] ; then if [ "$SIMUS_PHY" = "1" ] ; then
...@@ -640,7 +656,7 @@ function main() { ...@@ -640,7 +656,7 @@ function main() {
[ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build [ "$CLEAN" = "1" ] && rm -rf $DIR/$oaisim_build_dir/build
mkdir -p $DIR/$oaisim_build_dir/build mkdir -p $DIR/$oaisim_build_dir/build
cd $DIR/$oaisim_build_dir/build cd $DIR/$oaisim_build_dir/build
cmake .. eval $CMAKE_CMD
compilations \ compilations \
$oaisim_build_dir $oaisim_exec \ $oaisim_build_dir $oaisim_exec \
$oaisim_exec $dbin/$oaisim_exec.$REL $oaisim_exec $dbin/$oaisim_exec.$REL
...@@ -651,7 +667,7 @@ function main() { ...@@ -651,7 +667,7 @@ function main() {
echo_info "Compiling at_nas_ue" echo_info "Compiling at_nas_ue"
mkdir -p $DIR/at_commands/build mkdir -p $DIR/at_commands/build
cd $DIR/at_commands/build cd $DIR/at_commands/build
cmake .. eval $CMAKE_CMD
compilations \ compilations \
at_commands at_nas_ue \ at_commands at_nas_ue \
at_nas_ue $dbin/at_nas_ue at_nas_ue $dbin/at_nas_ue
...@@ -665,7 +681,7 @@ function main() { ...@@ -665,7 +681,7 @@ function main() {
[ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build [ "$CLEAN" = "1" ] && rm -rf $DIR/nas_sim_tools/build
mkdir -p $DIR/nas_sim_tools/build mkdir -p $DIR/nas_sim_tools/build
cd $DIR/nas_sim_tools/build cd $DIR/nas_sim_tools/build
cmake .. eval $CMAKE_CMD
compilations \ compilations \
nas_sim_tools usim \ nas_sim_tools usim \
usim $dbin/usim usim $dbin/usim
...@@ -722,7 +738,7 @@ function main() { ...@@ -722,7 +738,7 @@ function main() {
#[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build #[ "$CLEAN" = "1" ] && rm -rf $DIR/oaisim_mme_build_oai/build
#mkdir -p $DIR/oaisim_mme_build_oai/build #mkdir -p $DIR/oaisim_mme_build_oai/build
#cd $DIR/oaisim_mme_build_oai/build #cd $DIR/oaisim_mme_build_oai/build
#cmake .. #eval $CMAKE_CMD
#compilations \ #compilations \
# oaisim_mme_build_oai oaisim_mme \ # oaisim_mme_build_oai oaisim_mme \
# oaisim_mme $dbin/oaisim_mme.$REL # oaisim_mme $dbin/oaisim_mme.$REL
...@@ -752,7 +768,7 @@ function main() { ...@@ -752,7 +768,7 @@ function main() {
echo "set ( T_TRACER $T_TRACER )" >> $cmake_file echo "set ( T_TRACER $T_TRACER )" >> $cmake_file
echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file
cd $DIR/$rrh_build_dir/build cd $DIR/$rrh_build_dir/build
cmake .. eval $CMAKE_CMD
compilations \ compilations \
rrh_gw rrh_gw \ rrh_gw rrh_gw \
rrh_gw $dbin/rrh_gw rrh_gw $dbin/rrh_gw
...@@ -761,9 +777,9 @@ function main() { ...@@ -761,9 +777,9 @@ function main() {
# build RF device and transport protocol libraries # build RF device and transport protocol libraries
##################################### #####################################
if [ "$eNB" = "1" -o "$RRH" = "1" ] ; then if [ "$eNB" = "1" -o "$UE" = "1" -o "$RRH" = "1" ] ; then
if [ "$eNB" = "1" ] ; then if [ "$eNB" = "1" -o "$UE" = "1" ] ; then
build_dir=$lte_build_dir build_dir=$lte_build_dir
else else
build_dir=$rrh_build_dir build_dir=$rrh_build_dir
...@@ -847,7 +863,7 @@ fi ...@@ -847,7 +863,7 @@ fi
[ "$CLEAN" = "1" ] && rm -rf $OPENAIR_DIR/cmake_targets/doxygen/build [ "$CLEAN" = "1" ] && rm -rf $OPENAIR_DIR/cmake_targets/doxygen/build
mkdir -p $OPENAIR_DIR/cmake_targets/doxygen/build mkdir -p $OPENAIR_DIR/cmake_targets/doxygen/build
cd $OPENAIR_DIR/cmake_targets/doxygen/build cd $OPENAIR_DIR/cmake_targets/doxygen/build
cmake .. eval $CMAKE_CMD
make doc make doc
) >& $doxygen_log ) >& $doxygen_log
fi fi
......
#!/bin/bash
#sudo ./build_oai -c -C -I --install-optional-packages --install-system-files --UE -w USRP -V
#sudo ./build_oai -c -C -I --install-optional-packages --UE -w USRP -V
#sudo ./build_oai -c -C --UE -w USRP -V
sudo ./build_oai -c -C --UE -w USRP
#sudo ./build_oai -c -C --UE -w USRP --build-eclipse
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
# #
####################################### #######################################
LTEIF=oip0 LTEIF=oip1
#OPENAIR_DIR=/home/oai/svn-oai/openair4G #OPENAIR_DIR=/home/oai/svn-oai/openair4G
load_module() { load_module() {
...@@ -48,11 +48,11 @@ load_module() { ...@@ -48,11 +48,11 @@ load_module() {
sudo insmod $1 sudo insmod $1
} }
load_module $OPENAIR_DIR/targets/bin/ue_ip.ko load_module ../../targets/bin/ue_ip.ko
if [ "$1" = "UE" ]; then if [ "$1" = "UE" ]; then
echo "bring up oip0 interface for UE" echo "bring up $LTEIF interface for UE"
ifconfig oip0 up ifconfig $LTEIF up
fi fi
ip route flush cache ip route flush cache
......
#!/bin/bash
# Carrier frequency in Hz
#FREQ=2660000000 #FDD
FREQ=2350000000 #TDD
NRB=50
TA=0
#9:trace, 8/7:debug, 6:info, 4:warn, 3:error
LOGLEVEL=6
#enable or disable soft scope
#SCOPE=''
SCOPE='-d'
#enable or disable VCD logging
VCD=''
#VCD='-V'
ISTDD='-T'
#ISTDD=''
#use external clock
ECLK="--external-clock"
#ECLK=""
#UE scan carrier
#ISSCAN="--ue-scan-carrier"
ISSCAN=""
sudo sh -c './init_nas_s1 UE'
cd ../../targets/bin/
sudo -E ./lte-softmodem.Rel10 -U -C$FREQ -r$NRB $ISSCAN --ue-txgain 70 --ue-rxgain 80 -A $TA $ECLK -W $ISTDD -g $LOGLEVEL $SCOPE 2>&1 | sudo tee /tmp/UE.log
...@@ -4799,7 +4799,7 @@ int check_dci_format1_1a_coherency(DCI_format_t dci_format, ...@@ -4799,7 +4799,7 @@ int check_dci_format1_1a_coherency(DCI_format_t dci_format,
return(0); return(0);
} }
if(harq_pid >8) if(harq_pid>=8)
{ {
LOG_I(PHY,"bad harq id \n"); LOG_I(PHY,"bad harq id \n");
return(0); return(0);
...@@ -5013,7 +5013,7 @@ int check_dci_format2_2a_coherency(DCI_format_t dci_format, ...@@ -5013,7 +5013,7 @@ int check_dci_format2_2a_coherency(DCI_format_t dci_format,
#endif #endif
// I- check dci content minimum coherency // I- check dci content minimum coherency
if(harq_pid >8) if(harq_pid>=8)
{ {
LOG_I(PHY,"bad harq pid\n"); LOG_I(PHY,"bad harq pid\n");
return(0); return(0);
......
...@@ -258,7 +258,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue, ...@@ -258,7 +258,7 @@ int generate_ue_ulsch_params_from_rar(PHY_VARS_UE *ue,
if (ulsch->harq_processes[harq_pid]->nb_rb > 4) { if (ulsch->harq_processes[harq_pid]->nb_rb > 4) {
msg("rar_tools.c: unlikely rb count for RAR grant : nb_rb > 3\n"); msg("rar_tools.c: unlikely rb count for RAR grant : nb_rb > 3\n");
return(-1); // return(-1);
} }
// ulsch->harq_processes[harq_pid]->Ndi = 1; // ulsch->harq_processes[harq_pid]->Ndi = 1;
......
...@@ -242,7 +242,7 @@ uint32_t ulsch_encoding(uint8_t *a, ...@@ -242,7 +242,7 @@ uint32_t ulsch_encoding(uint8_t *a,
return(-1); return(-1);
} }
if (harq_pid > 7) { if (harq_pid >= 8) {
LOG_E(PHY,"Illegal harq_pid %d\n",harq_pid); LOG_E(PHY,"Illegal harq_pid %d\n",harq_pid);
return(-1); return(-1);
} }
......
...@@ -402,7 +402,7 @@ void ulsch_modulation(int32_t **txdataF, ...@@ -402,7 +402,7 @@ void ulsch_modulation(int32_t **txdataF,
// x1 is set in lte_gold_generic // x1 is set in lte_gold_generic
x2 = (ulsch->rnti<<14) + (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1 x2 = (ulsch->rnti<<14) + (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
if (harq_pid > 7) { if (harq_pid>=8) {
printf("ulsch_modulation.c: Illegal harq_pid %d\n",harq_pid); printf("ulsch_modulation.c: Illegal harq_pid %d\n",harq_pid);
return; return;
} }
......
...@@ -493,6 +493,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, ...@@ -493,6 +493,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
int16_t **chest_f; int16_t **chest_f;
int16_t *pdsch_llr; int16_t *pdsch_llr;
int16_t *pdsch_comp; int16_t *pdsch_comp;
int16_t *pdsch_mag;
int8_t *pdcch_llr; int8_t *pdcch_llr;
int16_t *pdcch_comp; int16_t *pdcch_comp;
int8_t *pbch_llr; int8_t *pbch_llr;
...@@ -571,6 +572,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, ...@@ -571,6 +572,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0]; // stream 0 pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->llr[0]; // stream 0
// pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0 // pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0
pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp0[0]; pdsch_comp = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->rxdataF_comp0[0];
pdsch_mag = (int16_t*) phy_vars_ue->pdsch_vars[subframe&0x1][eNB_id]->dl_ch_mag0[0];
// Received signal in time domain of receive antenna 0 // Received signal in time domain of receive antenna 0
if (rxsig_t != NULL) { if (rxsig_t != NULL) {
...@@ -752,8 +754,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, ...@@ -752,8 +754,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
for (k=0; k<frame_parms->symbols_per_tti; k++) { for (k=0; k<frame_parms->symbols_per_tti; k++) {
for (i=0; i<12*frame_parms->N_RB_DL/2; i++) { for (i=0; i<12*frame_parms->N_RB_DL/2; i++) {
I[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i]; int j = (2*frame_parms->N_RB_DL*12*k)+4*i;
Q[ind] = pdsch_comp[(2*frame_parms->N_RB_DL*12*k)+4*i+1]; I[ind] = (pdsch_mag[j ]!=0? 1.0/pdsch_mag[j ]: 0.0) * pdsch_comp[j ]*1.0;
Q[ind] = (pdsch_mag[j+1]!=0? 1.0/pdsch_mag[j+1]: 0.0) * pdsch_comp[j+1]*1.0;
ind++; ind++;
} }
} }
......
...@@ -190,7 +190,7 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) { ...@@ -190,7 +190,7 @@ int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
eNB = PHY_vars_eNB_g[Mod_idP][CC_id]; eNB = PHY_vars_eNB_g[Mod_idP][CC_id];
for (i=0; i<NUMBER_OF_UE_MAX; i++) { for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) { if ((eNB->dlsch[i]==NULL) || (eNB->ulsch[i]==NULL)) {
MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rnti); MSC_LOG_EVENT(MSC_PHY_ENB, "0 Failed remove ue %"PRIx16" (ENOMEM)", rntiP);
LOG_E(PHY,"Can't remove UE, not enough memory allocated\n"); LOG_E(PHY,"Can't remove UE, not enough memory allocated\n");
return(-1); return(-1);
} else { } else {
......
...@@ -633,7 +633,13 @@ PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type, ...@@ -633,7 +633,13 @@ PUCCH_FMT_t get_pucch_format(lte_frame_type_t frame_type,
} }
if(SR_payload == 1) if(SR_payload == 1)
{ {
if (frame_type == FDD) {
return pucch_format1; return pucch_format1;
} else if (frame_type == TDD) {
return pucch_format1b;
} else {
AssertFatal(1==0,"Unknown frame_type");
}
} }
} }
else else
...@@ -729,7 +735,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, ...@@ -729,7 +735,7 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue,
} else if (subframe == 8) { // ACK subframes 4 } else if (subframe == 8) { // ACK subframes 4
candidate_dl[0] = 4; candidate_dl[0] = 4;
} else { } else {
LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal tx-subframe %d for tdd_config %d\n",
ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config); ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config);
return(0); return(0);
} }
...@@ -743,8 +749,8 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue, ...@@ -743,8 +749,8 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue,
} }
} }
if (last_dl >= 10) { if (last_dl >= 10) {
LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n", LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal rx-subframe %d (tx-subframe %d) for tdd_config %d\n",
ue->Mod_id,proc->frame_tx,last_dl,frame_parms->tdd_config); ue->Mod_id,proc->frame_tx,last_dl,subframe,frame_parms->tdd_config);
return (0); return (0);
} }
...@@ -1775,13 +1781,13 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ...@@ -1775,13 +1781,13 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
} }
} }
ack_status_cw0 = reset_ack(&ue->frame_parms, ack_status_cw0 = get_ack(&ue->frame_parms,
ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack, ue->dlsch[proc->subframe_rx&0x1][eNB_id][0]->harq_ack,
subframe_tx, subframe_tx,
pucch_ack_payload, pucch_ack_payload,
0); 0);
ack_status_cw1 = reset_ack(&ue->frame_parms, ack_status_cw1 = get_ack(&ue->frame_parms,
ue->dlsch[proc->subframe_rx&0x1][eNB_id][1]->harq_ack, ue->dlsch[proc->subframe_rx&0x1][eNB_id][1]->harq_ack,
subframe_tx, subframe_tx,
pucch_ack_payload, pucch_ack_payload,
...@@ -3236,7 +3242,8 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo ...@@ -3236,7 +3242,8 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
ue->prach_resources[eNB_id]->ra_RNTI, ue->prach_resources[eNB_id]->ra_RNTI,
dlsch0->harq_processes[0]->b, dlsch0->harq_processes[0]->b,
&ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti, &ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti,
ue->prach_resources[eNB_id]->ra_PreambleIndex); ue->prach_resources[eNB_id]->ra_PreambleIndex,
dlsch0->harq_processes[0]->b); // alter the 'b' buffer so it contains only the selected RAR header and RAR payload
ue->pdcch_vars[(subframe_rx+1) & 0x1][eNB_id]->crnti = ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti; ue->pdcch_vars[(subframe_rx+1) & 0x1][eNB_id]->crnti = ue->pdcch_vars[subframe_rx & 0x1][eNB_id]->crnti;
......
...@@ -1301,7 +1301,7 @@ int main(int argc, char **argv) ...@@ -1301,7 +1301,7 @@ int main(int argc, char **argv)
unsigned int ret; unsigned int ret;
unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0; unsigned int coded_bits_per_codeword=0,nsymb; //,tbs=0;
unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0;//,num_layers; unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors[4]={0,0,0,0};//,num_layers;
//int re_allocated; //int re_allocated;
char fname[32],vname[32]; char fname[32],vname[32];
FILE *bler_fd; FILE *bler_fd;
...@@ -1998,7 +1998,7 @@ int main(int argc, char **argv) ...@@ -1998,7 +1998,7 @@ int main(int argc, char **argv)
} }
*/ */
UE->pdcch_vars[0][0]->crnti = n_rnti; UE->pdcch_vars[subframe & 0x1][0]->crnti = n_rnti;
// Fill in UL_alloc // Fill in UL_alloc
UL_alloc_pdu.type = 0; UL_alloc_pdu.type = 0;
...@@ -2246,7 +2246,10 @@ int main(int argc, char **argv) ...@@ -2246,7 +2246,10 @@ int main(int argc, char **argv)
round_trials[2] = 0; round_trials[2] = 0;
round_trials[3] = 0; round_trials[3] = 0;
dci_errors=0; dci_errors[0]=0;
dci_errors[1]=0;
dci_errors[2]=0;
dci_errors[3]=0;
// avg_ber = 0; // avg_ber = 0;
round=0; round=0;
...@@ -2499,6 +2502,9 @@ int main(int argc, char **argv) ...@@ -2499,6 +2502,9 @@ int main(int argc, char **argv)
if (UE->dlsch[subframe&0x1][0][0]->active == 0) { if (UE->dlsch[subframe&0x1][0][0]->active == 0) {
//printf("DCI not received\n"); //printf("DCI not received\n");
dci_errors[round]++;
UE->dlsch_errors[0] = 1;
/* /*
write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); write_output("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1);
write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],12*UE->frame_parms.N_RB_DL*3,1,1); write_output("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[eNB_id]->dl_ch_estimates_ext[0],12*UE->frame_parms.N_RB_DL*3,1,1);
...@@ -2837,13 +2843,13 @@ int main(int argc, char **argv) ...@@ -2837,13 +2843,13 @@ int main(int argc, char **argv)
double std_phy_proc_rx_demod=0; double std_phy_proc_rx_demod=0;
double std_phy_proc_rx_dec=0; double std_phy_proc_rx_dec=0;
effective_rate = ((double)(round_trials[0]-dci_errors)/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3])); effective_rate = 1.0-((double)(errs[0]+errs[1]+errs[2]+errs[3])/((double)round_trials[0] + round_trials[1] + round_trials[2] + round_trials[3]));
printf("\n**********************SNR = %f dB (tx_lev %f)**************************\n", printf("\n**********************SNR = %f dB (tx_lev %f)**************************\n",
SNR, SNR,
(double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12))); (double)tx_lev_dB+10*log10(UE->frame_parms.ofdm_symbol_size/(NB_RB*12)));
printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f (%2.1f%%,%f, %f), normalized delay %f (%f)\n", printf("Errors (%d(%d)/%d %d/%d %d/%d %d/%d), Pe = (%e,%e,%e,%e), dci_errors %d/%d, Pe = %e => effective rate %f, normalized delay %f (%f)\n",
errs[0], errs[0],
errs2[0], errs2[0],
round_trials[0], round_trials[0],
...@@ -2857,13 +2863,13 @@ int main(int argc, char **argv) ...@@ -2857,13 +2863,13 @@ int main(int argc, char **argv)
(double)errs[1]/(round_trials[0]), (double)errs[1]/(round_trials[0]),
(double)errs[2]/(round_trials[0]), (double)errs[2]/(round_trials[0]),
(double)errs[3]/(round_trials[0]), (double)errs[3]/(round_trials[0]),
dci_errors, dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3],
round_trials[0], round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3],
(double)dci_errors/(round_trials[0]), (double)(dci_errors[0]+dci_errors[1]+dci_errors[2]+dci_errors[3])/(round_trials[0]+round_trials[1]+round_trials[2]+round_trials[3]),
rate*effective_rate, //rate*effective_rate,
100*effective_rate, 100*effective_rate,
rate, //rate,
rate*get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs), //rate*get_Qm(UE->dlsch[subframe&0x1][0][0]->harq_processes[UE->dlsch[subframe&0x1][0][0]->current_harq_pid]->mcs),
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
...@@ -2986,7 +2992,7 @@ int main(int argc, char **argv) ...@@ -2986,7 +2992,7 @@ int main(int argc, char **argv)
round_trials[2], round_trials[2],
errs[3], errs[3],
round_trials[3], round_trials[3],
dci_errors); dci_errors[0]);
} else { } else {
fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n", fprintf(bler_fd,"%f;%d;%d;%d;%d;%f;%d;%d;%d;%d;%d;%d;%d;%d;%d\n",
SNR, SNR,
...@@ -3002,7 +3008,7 @@ int main(int argc, char **argv) ...@@ -3002,7 +3008,7 @@ int main(int argc, char **argv)
round_trials[2], round_trials[2],
errs[3], errs[3],
round_trials[3], round_trials[3],
dci_errors); dci_errors[0]);
} }
...@@ -3035,7 +3041,7 @@ int main(int argc, char **argv) ...@@ -3035,7 +3041,7 @@ int main(int argc, char **argv)
round_trials[2], round_trials[2],
errs[3], errs[3],
round_trials[3], round_trials[3],
dci_errors); dci_errors[0]);
//fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", fprintf(time_meas_fd,"%f;%d;%d;%f; %2.1f%%;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
...@@ -3058,9 +3064,9 @@ int main(int argc, char **argv) ...@@ -3058,9 +3064,9 @@ int main(int argc, char **argv)
(double)errs[1]/(round_trials[0]), (double)errs[1]/(round_trials[0]),
(double)errs[2]/(round_trials[0]), (double)errs[2]/(round_trials[0]),
(double)errs[3]/(round_trials[0]), (double)errs[3]/(round_trials[0]),
dci_errors, dci_errors[0],
round_trials[0], round_trials[0],
(double)dci_errors/(round_trials[0]), (double)dci_errors[0]/(round_trials[0]),
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
...@@ -3079,7 +3085,7 @@ int main(int argc, char **argv) ...@@ -3079,7 +3085,7 @@ int main(int argc, char **argv)
round_trials[2], round_trials[2],
errs[3], errs[3],
round_trials[3], round_trials[3],
dci_errors); dci_errors[0]);
//fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n"); //fprintf(time_meas_fd,"SNR; MCS; TBS; rate; DL_DECOD_ITER; err0; trials0; err1; trials1; err2; trials2; err3; trials3; PE; dci_err;PE;ND;\n");
fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;", fprintf(time_meas_fd,"%f;%d;%d;%d;%d;%f;%2.1f;%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%e;%e;%e;%e;%d;%d;%e;%f;%f;",
...@@ -3103,9 +3109,9 @@ int main(int argc, char **argv) ...@@ -3103,9 +3109,9 @@ int main(int argc, char **argv)
(double)errs[1]/(round_trials[0]), (double)errs[1]/(round_trials[0]),
(double)errs[2]/(round_trials[0]), (double)errs[2]/(round_trials[0]),
(double)errs[3]/(round_trials[0]), (double)errs[3]/(round_trials[0]),
dci_errors, dci_errors[0],
round_trials[0], round_trials[0],
(double)dci_errors/(round_trials[0]), (double)dci_errors[0]/(round_trials[0]),
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/ (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])/
(double)eNB->dlsch[0][0]->harq_processes[0]->TBS, (double)eNB->dlsch[0][0]->harq_processes[0]->TBS,
(1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0])); (1.0*(round_trials[0]-errs[0])+2.0*(round_trials[1]-errs[1])+3.0*(round_trials[2]-errs[2])+4.0*(round_trials[3]-errs[3]))/((double)round_trials[0]));
......
...@@ -653,6 +653,7 @@ int main(int argc, char **argv) ...@@ -653,6 +653,7 @@ int main(int argc, char **argv)
printf("-h This message\n"); printf("-h This message\n");
printf("-a Use AWGN channel and not multipath\n"); printf("-a Use AWGN channel and not multipath\n");
printf("-c TDD config\n"); printf("-c TDD config\n");
printf("-S Subframe number (0..9)\n");
printf("-R N_RB_DL\n"); printf("-R N_RB_DL\n");
printf("-F use FDD frame\n"); printf("-F use FDD frame\n");
printf("-p Use extended prefix mode\n"); printf("-p Use extended prefix mode\n");
......
...@@ -388,9 +388,9 @@ typedef struct { ...@@ -388,9 +388,9 @@ typedef struct {
struct PMCH_InfoList_r9 *pmch_InfoList struct PMCH_InfoList_r9 *pmch_InfoList
#endif #endif
); );
unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, char*); unsigned int (*mac_rlc_data_req)(module_id_t, unsigned int, const unsigned int,char*);
void (*mac_rlc_data_ind)(module_id_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* ); void (*mac_rlc_data_ind)(module_id_t, logical_chan_id_t, char*, tb_size_t, num_tb_t, crc_t* );
mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP, mac_rlc_status_resp_t (*mac_rlc_status_ind) (module_id_t enb_mod_idP, module_id_t ue_mod_idP, frame_t frameP, sub_frame_t subframeP, eNB_flag_t eNB_flagP, MBMS_flag_t MBMS_flagP,
logical_chan_id_t channel_idP, tb_size_t tb_sizeP); logical_chan_id_t channel_idP, tb_size_t tb_sizeP);
signed int (*rrc_rlc_data_req)(module_id_t, rb_id_t, mui_t, confirm_t, sdu_size_t, char *); signed int (*rrc_rlc_data_req)(module_id_t, rb_id_t, mui_t, confirm_t, sdu_size_t, char *);
void (*rrc_rlc_register_rrc) (void (*rrc_data_indP)(module_id_t , rb_id_t , sdu_size_t , char* ), void (*rrc_rlc_register_rrc) (void (*rrc_data_indP)(module_id_t , rb_id_t , sdu_size_t , char* ),
......
...@@ -562,14 +562,16 @@ int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) { ...@@ -562,14 +562,16 @@ int flexran_get_ue_wcqi (mid_t mod_id, mid_t ue_id) {
int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { int flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id); rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id); uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0); uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id,frame,subframe,ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0);
return rlc_status.bytes_in_buffer; return rlc_status.bytes_in_buffer;
} }
int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { int flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) {
rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id); rnti_t rnti = flexran_get_ue_crnti(mod_id,ue_id);
uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id); uint16_t frame = (uint16_t) flexran_get_current_frame(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0); uint16_t subframe = (uint16_t) flexran_get_current_subframe(mod_id);
mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0);
return rlc_status.head_sdu_creation_time; return rlc_status.head_sdu_creation_time;
} }
......
...@@ -332,16 +332,18 @@ rrc_mac_config_req( ...@@ -332,16 +332,18 @@ rrc_mac_config_req(
if (eNB_flagP == 0) { if (eNB_flagP == 0) {
if (measObj!= NULL) { if (measObj!= NULL) {
if (measObj[0]!= NULL) { if (measObj[0]!= NULL) {
if (measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList != NULL) {
UE_mac_inst[Mod_idP].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count; UE_mac_inst[Mod_idP].n_adj_cells = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.count;
LOG_I(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_idP].n_adj_cells); LOG_D(MAC,"Number of adjacent cells %d\n",UE_mac_inst[Mod_idP].n_adj_cells);
for (i=0; i<UE_mac_inst[Mod_idP].n_adj_cells; i++) { for (i=0; i<UE_mac_inst[Mod_idP].n_adj_cells; i++) {
UE_mac_inst[Mod_idP].adj_cell_id[i] = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.array[i]->physCellId; UE_mac_inst[Mod_idP].adj_cell_id[i] = measObj[0]->measObject.choice.measObjectEUTRA.cellsToAddModList->list.array[i]->physCellId;
LOG_I(MAC,"Cell %d : Nid_cell %d\n",i,UE_mac_inst[Mod_idP].adj_cell_id[i]); LOG_D(MAC,"Cell %d : Nid_cell %d\n",i,UE_mac_inst[Mod_idP].adj_cell_id[i]);
} }
mac_xface->phy_config_meas_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].n_adj_cells,UE_mac_inst[Mod_idP].adj_cell_id); mac_xface->phy_config_meas_ue(Mod_idP,0,eNB_index,UE_mac_inst[Mod_idP].n_adj_cells,UE_mac_inst[Mod_idP].adj_cell_id);
} }
}
/* /*
if (quantityConfig != NULL) { if (quantityConfig != NULL) {
......
...@@ -821,6 +821,7 @@ schedule_ue_spec( ...@@ -821,6 +821,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
...@@ -839,6 +840,7 @@ schedule_ue_spec( ...@@ -839,6 +840,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
TBS, //not used
(char *)&dlsch_buffer[0]); (char *)&dlsch_buffer[0]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
...@@ -872,6 +874,7 @@ schedule_ue_spec( ...@@ -872,6 +874,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH+1, DCCH+1,
...@@ -890,6 +893,7 @@ schedule_ue_spec( ...@@ -890,6 +893,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
DCCH+1, DCCH+1,
TBS, //not used
(char *)&dlsch_buffer[sdu_length_total]); (char *)&dlsch_buffer[sdu_length_total]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
...@@ -932,6 +936,7 @@ schedule_ue_spec( ...@@ -932,6 +936,7 @@ schedule_ue_spec(
rnti, rnti,
module_idP, module_idP,
frameP, frameP,
subframeP,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -949,6 +954,7 @@ schedule_ue_spec( ...@@ -949,6 +954,7 @@ schedule_ue_spec(
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
TBS, //not used
(char*)&dlsch_buffer[sdu_length_total]); (char*)&dlsch_buffer[sdu_length_total]);
T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP),
T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus])); T_INT(harq_pid), T_INT(lcid), T_INT(sdu_lengths[num_sdus]));
......
...@@ -504,7 +504,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra ...@@ -504,7 +504,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
module_idP,CC_id,frameP,MTCH,TBS, module_idP,CC_id,frameP,MTCH,TBS,
TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
rlc_status = mac_rlc_status_ind(module_idP,0,frameP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH, rlc_status = mac_rlc_status_ind(module_idP,0,frameP,subframeP,module_idP,ENB_FLAG_YES,MBMS_FLAG_YES,MTCH,
TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch); TBS-header_len_mcch-header_len_msi-sdu_length_total-header_len_mtch);
LOG_D(MAC,"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n", LOG_D(MAC,"e-MBMS log channel %u frameP %d, subframeP %d, rlc_status.bytes_in_buffer is %d\n",
MTCH,frameP,subframeP, rlc_status.bytes_in_buffer); MTCH,frameP,subframeP, rlc_status.bytes_in_buffer);
...@@ -521,6 +521,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra ...@@ -521,6 +521,7 @@ int schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, sub_fra
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_YES, MBMS_FLAG_YES,
MTCH, MTCH,
0, //not used
(char*)&mch_buffer[sdu_length_total]); (char*)&mch_buffer[sdu_length_total]);
//sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]); //sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP,frameP, MBMS_FLAG_NO, MTCH+(MAX_NUM_RB*(NUMBER_OF_UE_MAX+1)), (char*)&mch_buffer[sdu_length_total]);
LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",module_idP,CC_id,sdu_lengths[num_sdus],MTCH); LOG_I(MAC,"[eNB %d][MBMS USER-PLANE] CC_id %d Got %d bytes for MTCH %d\n",module_idP,CC_id,sdu_lengths[num_sdus],MTCH);
......
...@@ -174,6 +174,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ...@@ -174,6 +174,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ...@@ -193,6 +194,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
...@@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id, ...@@ -209,6 +211,7 @@ void flexran_apply_ue_spec_scheduling_decisions(mid_t mod_id,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
lcid, lcid,
rlc_size, //not used
(char *)&dlsch_buffer[sdu_length_total]); (char *)&dlsch_buffer[sdu_length_total]);
LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]); LOG_D(MAC,"[eNB %d][LCID %d] CC_id %d Got %d bytes from RLC\n",mod_id, lcid, CC_id, sdu_lengths[j]);
......
...@@ -160,7 +160,7 @@ void _store_dlsch_buffer (module_id_t Mod_id, ...@@ -160,7 +160,7 @@ void _store_dlsch_buffer (module_id_t Mod_id,
for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
...@@ -1241,6 +1241,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id, ...@@ -1241,6 +1241,7 @@ flexran_schedule_ue_spec_common(mid_t mod_id,
rnti, rnti,
mod_id, mod_id,
frame, frame,
subframe,
ENB_FLAG_YES, ENB_FLAG_YES,
MBMS_FLAG_NO, MBMS_FLAG_NO,
j, j,
......
...@@ -109,7 +109,7 @@ void store_dlsch_buffer (module_id_t Mod_id, ...@@ -109,7 +109,7 @@ void store_dlsch_buffer (module_id_t Mod_id,
for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels for(i=0; i< MAX_NUM_LCID; i++) { // loop over all the logical channels
rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 ); rlc_status = mac_rlc_status_ind(Mod_id,rnti, Mod_id,frameP,subframeP,ENB_FLAG_YES,MBMS_FLAG_NO,i,0 );
UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel UE_template->dl_buffer_info[i] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel
UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer; UE_template->dl_pdus_in_buffer[i] = rlc_status.pdus_in_buffer;
UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ; UE_template->dl_buffer_head_sdu_creation_time[i] = rlc_status.head_sdu_creation_time ;
......
...@@ -454,6 +454,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,u ...@@ -454,6 +454,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,u
@param t_crnti Pointer to PHY variable containing the T_CRNTI @param t_crnti Pointer to PHY variable containing the T_CRNTI
@param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of @param preamble_index Preamble Index used by PHY to transmit the PRACH. This should match the received RAR to trigger the rest of
random-access procedure random-access procedure
@param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload
@returns timing advance or 0xffff if preamble doesn't match @returns timing advance or 0xffff if preamble doesn't match
*/ */
uint16_t uint16_t
...@@ -464,7 +465,8 @@ ue_process_rar( ...@@ -464,7 +465,8 @@ ue_process_rar(
const rnti_t ra_rnti, const rnti_t ra_rnti,
uint8_t * const dlsch_buffer, uint8_t * const dlsch_buffer,
rnti_t * const t_crnti, rnti_t * const t_crnti,
const uint8_t preamble_index const uint8_t preamble_index,
uint8_t* selected_rar_buffer
); );
......
...@@ -394,7 +394,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, ...@@ -394,7 +394,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
} else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) { } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] > 0) {
// This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example) // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element dcch_header_len = 2 + 2; /// SHORT Subheader + C-RNTI control element
rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO, rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
DCCH, DCCH,
6); 6);
...@@ -409,6 +409,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, ...@@ -409,6 +409,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP,
sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,
eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO, eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
DCCH, DCCH,
6, //not used
(char *)&ulsch_buff[0]); (char *)&ulsch_buff[0]);
LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]); LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
......
...@@ -136,15 +136,48 @@ ue_process_rar( ...@@ -136,15 +136,48 @@ ue_process_rar(
const rnti_t ra_rnti, const rnti_t ra_rnti,
uint8_t* const dlsch_buffer, uint8_t* const dlsch_buffer,
rnti_t* const t_crnti, rnti_t* const t_crnti,
const uint8_t preamble_index const uint8_t preamble_index,
uint8_t* selected_rar_buffer // output argument for storing the selected RAR header and RAR payload
) )
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
{ {
uint16_t ret = 0; // return value
RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer; RA_HEADER_RAPID *rarh = (RA_HEADER_RAPID *)dlsch_buffer;
// RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1); // RAR_PDU *rar = (RAR_PDU *)(dlsch_buffer+1);
uint8_t *rar = (uint8_t *)(dlsch_buffer+1); uint8_t *rar = (uint8_t *)(dlsch_buffer+1);
// get the last RAR payload for working with CMW500
uint8_t n_rarpy = 0; // number of RAR payloads
uint8_t n_rarh = 0; // number of MAC RAR subheaders
uint8_t best_rx_rapid = -1; // the closest RAPID receive from all RARs
while (1) {
n_rarh++;
if (rarh->T == 1) {
n_rarpy++;
LOG_D(MAC, "RAPID %d\n", rarh->RAPID);
}
if (rarh->RAPID == preamble_index) {
LOG_D(PHY, "Found RAR with the intended RAPID %d\n", rarh->RAPID);
rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6);
break;
}
if (abs((int)rarh->RAPID - (int)preamble_index) < abs((int)best_rx_rapid - (int)preamble_index)) {
best_rx_rapid = rarh->RAPID;
rar = (uint8_t *)(dlsch_buffer+n_rarh + (n_rarpy-1)*6);
}
if (rarh->E == 0) {
LOG_I(PHY, "No RAR found with the intended RAPID. The closest RAPID in all RARs is %d\n", best_rx_rapid);
break;
} else {
rarh++;
}
};
LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", n_rarh, n_rarpy);
if (CC_id>0) { if (CC_id>0) {
LOG_W(MAC,"Should not have received RAR on secondary CCs! \n"); LOG_W(MAC,"Should not have received RAR on secondary CCs! \n");
return(0xffff); return(0xffff);
...@@ -172,7 +205,7 @@ ue_process_rar( ...@@ -172,7 +205,7 @@ ue_process_rar(
if (opt_enabled) { if (opt_enabled) {
LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n", LOG_D(OPT,"[UE %d][RAPROC] CC_id %d RAR Frame %d trace pdu for ra-RNTI %x\n",
module_idP, CC_id, frameP, ra_rnti); module_idP, CC_id, frameP, ra_rnti);
trace_pdu(1, (uint8_t*)rarh, 7, module_idP, 2, ra_rnti, trace_pdu(1, (uint8_t*)dlsch_buffer, n_rarh + n_rarpy*6, module_idP, 2, ra_rnti,
UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0); UE_mac_inst[module_idP].rxFrame, UE_mac_inst[module_idP].rxSubframe, 0, 0);
} }
...@@ -180,9 +213,16 @@ ue_process_rar( ...@@ -180,9 +213,16 @@ ue_process_rar(
*t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti; *t_crnti = (uint16_t)rar[5]+(rar[4]<<8);//rar->t_crnti;
UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti; UE_mac_inst[module_idP].crnti = *t_crnti;//rar->t_crnti;
//return(rar->Timing_Advance_Command); //return(rar->Timing_Advance_Command);
return((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4)); ret = ((((uint16_t)(rar[0]&0x7f))<<4) + (rar[1]>>4));
} else { } else {
UE_mac_inst[module_idP].crnti=0; UE_mac_inst[module_idP].crnti=0;
return(0xffff); ret = (0xffff);
} }
// move the selected RAR to the front of the RA_PDSCH buffer
memcpy(selected_rar_buffer+0, (uint8_t*)rarh, 1);
memcpy(selected_rar_buffer+1, (uint8_t*)rar , 6);
return ret;
} }
This diff is collapsed.
This diff is collapsed.
...@@ -267,23 +267,32 @@ private_rlc_am( void rlc_am_get_pdus (const protocol_ctxt_t* const ctxtP,v ...@@ -267,23 +267,32 @@ private_rlc_am( void rlc_am_get_pdus (const protocol_ctxt_t* const ctxtP,v
*/ */
protected_rlc_am( void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind);) protected_rlc_am( 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, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) /*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, uint16_t tbs_sizeP, 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. * \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] ctxt_pP Running context.
* \param[in] rlc_pP RLC AM protocol instance pointer. * \param[in] rlc_pP RLC AM protocol instance pointer.
* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission.
* \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \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. * \return The maximum number of bytes that can be served by RLC instance to MAC.
*/ */
public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);) public_rlc_am( struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, 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) /*! \fn void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP)
* \brief Set available TBS for RLC Tx just before am_mac_data_request. Used for UE only.
* \param[in] rlc_pP RLC AM protocol instance pointer.
* \param[in] tb_sizeP Available Tx Transport Block size in bytes.
*/
public_rlc_am( void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP);)
/*! \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. * \brief Gives PDUs to lower layer MAC.
* \param[in] ctxt_pP Running context. * \param[in] ctxt_pP Running context.
* \param[in] rlc_pP RLC AM protocol instance pointer. * \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. * \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.
*/ */
public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP);) public_rlc_am( 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) /*! \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. * \brief Receive PDUs from lower layer MAC.
...@@ -293,6 +302,13 @@ public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ct ...@@ -293,6 +302,13 @@ public_rlc_am( struct mac_data_req rlc_am_mac_data_request (const protocol_ct
*/ */
public_rlc_am( void rlc_am_mac_data_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind data_indP);) public_rlc_am( 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.
*/
public_rlc_am( 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) /*! \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. * \brief Interface with higher layers, buffer higher layer SDUS for transmission.
* \param[in] ctxt_pP Running context. * \param[in] ctxt_pP Running context.
......
...@@ -48,14 +48,17 @@ ...@@ -48,14 +48,17 @@
# define RLC_AM_SDU_DATA_BUFFER_SIZE 64*1024 # 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. */ /** 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 128 # define RLC_AM_SDU_CONTROL_BUFFER_SIZE 1024
/** Size of the retransmission buffer (number of PDUs). */ /** Size of the retransmission buffer (number of PDUs). */
# define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_SN_MODULO # define RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE RLC_AM_WINDOW_SIZE
/** PDU minimal header size in bytes. */ /** PDU minimal header size in bytes. */
# define RLC_AM_HEADER_MIN_SIZE 2 # 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. */ /** 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 # define RLC_AM_MIN_SEGMENT_SIZE_REQUEST 8
...@@ -69,6 +72,99 @@ ...@@ -69,6 +72,99 @@
# define RLC_AM_MAX_NACK_IN_STATUS_PDU 1023 # 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. */ /** Max holes created by NACK_SN with segment offsets for a PDU in the retransmission buffer. */
# define RLC_AM_MAX_HOLES_REPORT_PER_PDU 32 # define RLC_AM_MAX_HOLES_REPORT_PER_PDU 16
/** @} */ /** @} */
# endif
#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
...@@ -57,7 +57,6 @@ typedef struct rlc_am_entity_s { ...@@ -57,7 +57,6 @@ typedef struct rlc_am_entity_s {
boolean_t 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. */ boolean_t 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 sdu_buffer_occupancy; /*!< \brief Number of bytes of unsegmented SDUs. */
rlc_buffer_occupancy_t retransmission_buffer_occupancy; /*!< \brief Number of bytes of PDUs in retransmission buffer waiting for a ACK. */
rlc_buffer_occupancy_t status_buffer_occupancy; /*!< \brief Number of bytes of control PDUs waiting for transmission. */ 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; rlc_am_control_pdu_info_t control_pdu_info;
...@@ -69,17 +68,14 @@ typedef struct rlc_am_entity_s { ...@@ -69,17 +68,14 @@ typedef struct rlc_am_entity_s {
pthread_mutex_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). */ 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; /*!< \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. */ 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 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. */ 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 *pdu_retrans_buffer; /*!< \brief Retransmission buffer. */ 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_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */
signed int retrans_num_bytes; /*!< \brief Number of bytes 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 */
signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. */
unsigned int num_nack_so; /*!< \brief Number of segment offsets asked to be retransmitted by peer RLC entity. */
unsigned int num_nack_sn; /*!< \brief Number of segment asked to be retransmitted by peer RLC entity. */
boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */ boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */
//--------------------------------------------------------------------- //---------------------------------------------------------------------
...@@ -137,7 +133,7 @@ typedef struct rlc_am_entity_s { ...@@ -137,7 +133,7 @@ typedef struct rlc_am_entity_s {
//----------------------------- //-----------------------------
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 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. */ 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. */
uint16_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. */ 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 // STATISTICS
...@@ -176,14 +172,14 @@ typedef struct rlc_am_entity_s { ...@@ -176,14 +172,14 @@ typedef struct rlc_am_entity_s {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
// OUTPUTS // OUTPUTS
//--------------------------------------------------------------------- //---------------------------------------------------------------------
sdu_size_t nb_bytes_requested_by_mac; /*!< \brief Number of bytes requested by lower layer for next transmission. */ 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 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 control_pdu_list; /*!< \brief Control PDUs buffered for transmission to MAC layer. */
rlc_sn_t first_retrans_pdu_sn; /*!< \brief Lowest sequence number of PDU to be retransmitted. */
list_t segmentation_pdu_list; /*!< \brief List of "freshly" segmented PDUs. */ list_t segmentation_pdu_list; /*!< \brief List of "freshly" segmented PDUs. */
boolean_t status_requested; /*!< \brief Status requested by peer. */ uint8_t status_requested; /*!< \brief Status bitmap requested by peer. */
frame_t last_frame_status_indication; /*!< \brief The last frame number a MAC status indication has been received by RLC. */ 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 // buffer occupancy measurements sent to MAC
//----------------------------- //-----------------------------
......
...@@ -41,21 +41,28 @@ void rlc_am_free_in_sdu( ...@@ -41,21 +41,28 @@ void rlc_am_free_in_sdu(
const unsigned int index_in_bufferP) const unsigned int index_in_bufferP)
{ {
if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) { if (index_in_bufferP <= RLC_AM_SDU_CONTROL_BUFFER_SIZE) {
/* BugFix: SDU shall have been already freed during initial PDU segmentation or concatenation !! */
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) { if (rlcP->input_sdus[index_in_bufferP].mem_block != NULL) {
free_mem_block(rlcP->input_sdus[index_in_bufferP].mem_block, __func__); 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].mem_block = NULL;
rlcP->nb_sdu_no_segmented -= 1; rlcP->nb_sdu_no_segmented -= 1;
rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0; rlcP->input_sdus[index_in_bufferP].sdu_remaining_size = 0;
} }
*/
rlcP->nb_sdu -= 1; rlcP->nb_sdu -= 1;
memset(&rlcP->input_sdus[index_in_bufferP], 0, sizeof(rlc_am_tx_sdu_management_t)); 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; 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) { if (rlcP->current_sdu_index == index_in_bufferP) {
rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE; 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) && while ((rlcP->current_sdu_index != rlcP->next_sdu_index) &&
(rlcP->input_sdus[rlcP->current_sdu_index].flags.transmitted_successfully == 1)) { (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; rlcP->current_sdu_index = (rlcP->current_sdu_index + 1) % RLC_AM_SDU_CONTROL_BUFFER_SIZE;
...@@ -100,3 +107,41 @@ rlc_am_in_sdu_is_empty( ...@@ -100,3 +107,41 @@ rlc_am_in_sdu_is_empty(
return 0; 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);
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);
}
}
}
...@@ -77,5 +77,13 @@ protected_rlc_am_in_sdu(void rlc_am_free_in_sdu_data (const protocol_ctxt_t* con ...@@ -77,5 +77,13 @@ protected_rlc_am_in_sdu(void rlc_am_free_in_sdu_data (const protocol_ctxt_t* con
* \return 1 if the buffer is empty, else 0. * \return 1 if the buffer is empty, else 0.
*/ */
protected_rlc_am_in_sdu(signed int rlc_am_in_sdu_is_empty(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP);) protected_rlc_am_in_sdu(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.
*/
protected_rlc_am_in_sdu(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 # endif
...@@ -51,16 +51,16 @@ rlc_am_init( ...@@ -51,16 +51,16 @@ rlc_am_init(
pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL); 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)); 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" //#warning "cast the rlc retrans buffer to uint32"
// rlc_pP->pdu_retrans_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, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
rlc_pP->pdu_retrans_buffer = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof( 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))); rlc_am_tx_data_pdu_management_t)));
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] input_sdus[] = %p element size=%zu\n", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->input_sdus, rlc_pP->input_sdus,
sizeof(rlc_am_tx_sdu_management_t)); sizeof(rlc_am_tx_sdu_management_t));
LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] pdu_retrans_buffer[] = %p element size=%zu\n", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->pdu_retrans_buffer, rlc_pP->tx_data_pdu_buffer,
sizeof(rlc_am_tx_data_pdu_management_t)); sizeof(rlc_am_tx_data_pdu_management_t));
// TX state variables // TX state variables
...@@ -74,12 +74,12 @@ rlc_am_init( ...@@ -74,12 +74,12 @@ rlc_am_init(
// RX state variables // RX state variables
//rlc_pP->vr_r = 0; //rlc_pP->vr_r = 0;
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE; rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
//rlc_pP->vr_x = 0; rlc_pP->vr_x = RLC_SN_UNDEFINED;
//rlc_pP->vr_ms = 0; //rlc_pP->vr_ms = 0;
//rlc_pP->vr_h = 0; //rlc_pP->vr_h = 0;
rlc_pP->sn_status_triggered_delayed = RLC_SN_UNDEFINED;
rlc_pP->last_frame_status_indication = 123456; // any value > 1 rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE; rlc_pP->initialized = TRUE;
} }
...@@ -128,12 +128,13 @@ rlc_am_reestablish( ...@@ -128,12 +128,13 @@ rlc_am_reestablish(
// RX state variables // RX state variables
rlc_pP->vr_r = 0; rlc_pP->vr_r = 0;
rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE; rlc_pP->vr_mr = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
rlc_pP->vr_x = 0; rlc_pP->vr_x = RLC_SN_UNDEFINED;
rlc_pP->vr_ms = 0; rlc_pP->vr_ms = 0;
rlc_pP->vr_h = 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_frame_status_indication = 123456; // any value > 1 rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1
rlc_pP->first_retrans_pdu_sn = -1;
rlc_pP->initialized = TRUE; rlc_pP->initialized = TRUE;
...@@ -172,16 +173,16 @@ rlc_am_cleanup( ...@@ -172,16 +173,16 @@ rlc_am_cleanup(
pthread_mutex_destroy(&rlc_pP->lock_input_sdus); pthread_mutex_destroy(&rlc_pP->lock_input_sdus);
if (rlc_pP->pdu_retrans_buffer != NULL) { if (rlc_pP->tx_data_pdu_buffer != NULL) {
for (i=0; i < RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE; i++) { for (i=0; i < RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE; i++) {
if (rlc_pP->pdu_retrans_buffer[i].mem_block != NULL) { if (rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block != NULL) {
free_mem_block(rlc_pP->pdu_retrans_buffer[i].mem_block, __func__); free_mem_block(rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block, __func__);
rlc_pP->pdu_retrans_buffer[i].mem_block = NULL; rlc_pP->tx_data_pdu_buffer[i % RLC_AM_WINDOW_SIZE].mem_block = NULL;
} }
} }
free(rlc_pP->pdu_retrans_buffer); free(rlc_pP->tx_data_pdu_buffer);
rlc_pP->pdu_retrans_buffer = NULL; rlc_pP->tx_data_pdu_buffer = NULL;
} }
memset(rlc_pP, 0, sizeof(rlc_am_entity_t)); memset(rlc_pP, 0, sizeof(rlc_am_entity_t));
......
...@@ -91,7 +91,7 @@ rlc_am_send_sdu ( ...@@ -91,7 +91,7 @@ rlc_am_send_sdu (
const protocol_ctxt_t* const ctxt_pP, const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t * const rlc_pP) rlc_am_entity_t * const rlc_pP)
{ {
# if TRACE_RLC_UM_PDU # if TRACE_RLC_AM_PDU
char message_string[7000]; char message_string[7000];
size_t message_string_size = 0; size_t message_string_size = 0;
#if ENABLE_ITTI #if ENABLE_ITTI
...@@ -212,7 +212,8 @@ void ...@@ -212,7 +212,8 @@ void
rlc_am_reassemble_pdu( rlc_am_reassemble_pdu(
const protocol_ctxt_t* const ctxt_pP, const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t * const rlc_pP, rlc_am_entity_t * const rlc_pP,
mem_block_t * const tb_pP) mem_block_t * const tb_pP,
boolean_t free_rlc_pdu)
{ {
int i,j; int i,j;
...@@ -397,5 +398,7 @@ rlc_am_reassemble_pdu( ...@@ -397,5 +398,7 @@ rlc_am_reassemble_pdu(
} }
} }
if (free_rlc_pdu) {
free_mem_block(tb_pP, __func__); free_mem_block(tb_pP, __func__);
}
} }
...@@ -72,13 +72,14 @@ private_rlc_am_reassembly( void rlc_am_reassembly (const protocol_ctxt_t* co ...@@ -72,13 +72,14 @@ private_rlc_am_reassembly( void rlc_am_reassembly (const protocol_ctxt_t* co
*/ */
private_rlc_am_reassembly( void rlc_am_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP);) private_rlc_am_reassembly( 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) /*! \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,boolean_t 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. * \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] ctxtP Running context.
* \param[in] rlc_pP RLC AM protocol instance pointer. * \param[in] rlc_pP RLC AM protocol instance pointer.
* \param[in] tb_pP RLC AM PDU embedded in a mem_block_t. * \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.
*/ */
protected_rlc_am_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);) protected_rlc_am_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,boolean_t free_rlc_pdu);)
/** @} */ /** @} */
#endif #endif
...@@ -50,21 +50,24 @@ ...@@ -50,21 +50,24 @@
# define public_rlc_am_retransmit(x) extern x # define public_rlc_am_retransmit(x) extern x
# endif # endif
# endif # endif
/*! \fn void rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, uint16_t snP, sdu_size_t so_startP, sdu_size_t so_endP) /*! \fn boolean_t 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. * \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] ctxtP Running context.
* \param[in] rlcP RLC AM protocol instance pointer. * \param[in] rlcP RLC AM protocol instance pointer.
* \param[in] snP Sequence number of the PDU that is negative acknowledged. * \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_startP Start of the segment offset of the PDU that .
* \param[in] so_endP Transport blocks received from MAC layer. * \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. * \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.
*/ */
protected_rlc_am_retransmit(void rlc_am_nack_pdu ( protected_rlc_am_retransmit(boolean_t rlc_am_nack_pdu (
const protocol_ctxt_t* const ctxt_pP, const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlcP, rlc_am_entity_t *const rlcP,
const rlc_sn_t snP, const rlc_sn_t snP,
const sdu_size_t so_startP, const rlc_sn_t prev_nack_snP,
const sdu_size_t so_endP);) 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) /*! \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. * \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
...@@ -90,6 +93,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_copy ( ...@@ -90,6 +93,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_copy (
rlc_am_entity_t *const rlcP, rlc_am_entity_t *const rlcP,
const rlc_sn_t snP)); const rlc_sn_t snP));
#if 0
/*! \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) /*! \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. * \brief The RLC AM PDU which have the sequence number snP is marked ACKed.
* \param[in] ctxtP Running context. * \param[in] ctxtP Running context.
...@@ -103,7 +107,18 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment ( ...@@ -103,7 +107,18 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment (
rlc_am_entity_t *const rlcP, rlc_am_entity_t *const rlcP,
const rlc_sn_t snP, const rlc_sn_t snP,
sdu_size_t *const sizeP)); sdu_size_t *const sizeP));
#endif
/*! \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
*/
protected_rlc_am_retransmit(mem_block_t* rlc_am_get_pdu_to_retransmit(
const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t* const rlcP);)
#if 0
/*! \fn void rlc_am_retransmit_any_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* 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. * \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] ctxtP Running context.
...@@ -112,6 +127,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment ( ...@@ -112,6 +127,7 @@ protected_rlc_am_retransmit(mem_block_t* rlc_am_retransmit_get_subsegment (
protected_rlc_am_retransmit(void rlc_am_retransmit_any_pdu( protected_rlc_am_retransmit(void rlc_am_retransmit_any_pdu(
const protocol_ctxt_t* const ctxt_pP, const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t* const rlcP);) rlc_am_entity_t* const rlcP);)
#endif
/*! \fn void rlc_am_tx_buffer_display (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t* rlcP, char* message_pP) /*! \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. * \brief Display the dump of the retransmission buffer.
......
...@@ -59,6 +59,16 @@ ...@@ -59,6 +59,16 @@
#include "PHY/defs.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.
*/
protected_rlc_am_rx_list( 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);)
#if 0
/*! \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) /*! \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). * \brief Insert a PDU in the RX buffer (implemented with a list).
* \param[in] ctxt_pP Running context. * \param[in] ctxt_pP Running context.
...@@ -67,6 +77,15 @@ ...@@ -67,6 +77,15 @@
* \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted. * \return Zero if the PDU could be inserted in the RX buffer, a negative value if the PDU could not be inserted.
*/ */
protected_rlc_am_rx_list( 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);) protected_rlc_am_rx_list( 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);)
#endif
/*! \fn boolean_t 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
*/
protected_rlc_am_rx_list( boolean_t 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) /*! \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. * \brief Check if all sub-segments of a PDU are received, if yes then call rlc_am_rx_mark_all_segments_received() procedure.
......
...@@ -39,7 +39,8 @@ void rlc_am_pdu_polling ( ...@@ -39,7 +39,8 @@ void rlc_am_pdu_polling (
const protocol_ctxt_t* const ctxt_pP, const protocol_ctxt_t* const ctxt_pP,
rlc_am_entity_t *const rlc_pP, rlc_am_entity_t *const rlc_pP,
rlc_am_pdu_sn_10_t *const pdu_pP, rlc_am_pdu_sn_10_t *const pdu_pP,
const int16_t payload_sizeP) const int16_t payload_sizeP,
boolean_t is_new_pdu)
{ {
// 5.2.2 Polling // 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. // An AM RLC entity can poll its peer AM RLC entity in order to trigger STATUS reporting at the peer AM RLC entity.
...@@ -68,49 +69,59 @@ void rlc_am_pdu_polling ( ...@@ -68,49 +69,59 @@ void rlc_am_pdu_polling (
// - start t-PollRetransmit; // - start t-PollRetransmit;
// - else: // - else:
// - restart t-PollRetransmit; // - restart t-PollRetransmit;
if (is_new_pdu) {
if (rlc_pP->poll_pdu != RLC_AM_POLL_PDU_INFINITE) {
rlc_pP->c_pdu_without_poll += 1; 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; rlc_pP->c_byte_without_poll += payload_sizeP;
}
}
if ( if (
(rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) || ((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->c_byte_without_poll >= rlc_pP->poll_byte))) ||
((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) || ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) ||
(rlc_pP->vt_s == rlc_pP->vt_ms) || (rlc_pP->vt_s == rlc_pP->vt_ms) ||
(rlc_pP->force_poll == TRUE) (rlc_pP->force_poll == true)
) { ) {
rlc_pP->force_poll = FALSE; rlc_pP->force_poll = false;
if (rlc_pP->c_pdu_without_poll >= rlc_pP->poll_pdu) { 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", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->poll_pdu); rlc_pP->poll_pdu);
} else }
if (rlc_pP->c_byte_without_poll >= rlc_pP->poll_byte) { 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", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->poll_byte); rlc_pP->poll_byte);
} else }
if ((rlc_pP->sdu_buffer_occupancy == 0) && (rlc_pP->retrans_num_bytes_to_retransmit == 0)) { 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", 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)); PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
} else }
if (rlc_pP->vt_s == rlc_pP->vt_ms) { 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", 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)); PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
} }
pdu_pP->b1 = pdu_pP->b1 | 0x20; RLC_AM_PDU_SET_POLL(pdu_pP->b1);
rlc_pP->c_pdu_without_poll = 0; rlc_pP->c_pdu_without_poll = 0;
rlc_pP->c_byte_without_poll = 0; rlc_pP->c_byte_without_poll = 0;
rlc_pP->poll_sn = (rlc_pP->vt_s -1) & RLC_AM_SN_MASK; // 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) { //optimisation if (!rlc_pP->t_poll_retransmit.running) {
rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP); rlc_am_start_timer_poll_retransmit(ctxt_pP, rlc_pP);
//optimisation } else { //optimisation } else {
//optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out; //optimisation rlc_pP->t_poll_retransmit.frame_time_out = ctxt_pP->frame + rlc_pP->t_poll_retransmit.time_out;
//optimisation } //optimisation }
} else { } else {
pdu_pP->b1 = pdu_pP->b1 & 0xDF; // 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);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -178,7 +189,9 @@ void rlc_am_segment_10 ( ...@@ -178,7 +189,9 @@ void rlc_am_segment_10 (
if (rlc_pP->nb_sdu_no_segmented <= 1) { if (rlc_pP->nb_sdu_no_segmented <= 1) {
max_li_overhead = 0; max_li_overhead = 0;
} else { } else {
max_li_overhead = (((rlc_pP->nb_sdu_no_segmented - 1) * 3) / 2) + ((rlc_pP->nb_sdu_no_segmented - 1) % 2); /* 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", LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] max_li_overhead %d\n",
...@@ -210,7 +223,7 @@ void rlc_am_segment_10 ( ...@@ -210,7 +223,7 @@ void rlc_am_segment_10 (
pdu_remaining_size = data_pdu_size - RLC_AM_HEADER_MIN_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_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_tb_req_p = (struct mac_tb_req*) (pdu_mem_p->data);
pdu_mngt_p = &rlc_pP->pdu_retrans_buffer[rlc_pP->vt_s % RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE]; 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_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)); memset (pdu_mem_p->data, 0, sizeof (rlc_am_pdu_sn_10_t)+sizeof(struct mac_tb_req));
...@@ -485,11 +498,11 @@ void rlc_am_segment_10 ( ...@@ -485,11 +498,11 @@ void rlc_am_segment_10 (
fi = fi + 1; fi = fi + 1;
} }
pdu_p->b1 = pdu_p->b1 | (fi << 3); pdu_p->b1 = pdu_p->b1 | (fi << RLC_AM_PDU_FI_OFFSET);
// set fist e bit // set fist e bit
if (fill_num_li > 0) { if (fill_num_li > 0) {
pdu_p->b1 = pdu_p->b1 | 0x04; 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", LOG_T(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEGMENT] SEND PDU SN %04d SIZE %d BYTES PAYLOAD SIZE %d BYTES\n",
...@@ -501,8 +514,9 @@ void rlc_am_segment_10 ( ...@@ -501,8 +514,9 @@ void rlc_am_segment_10 (
rlc_pP->stat_tx_data_pdu += 1; rlc_pP->stat_tx_data_pdu += 1;
rlc_pP->stat_tx_data_bytes += (data_pdu_size - pdu_remaining_size); rlc_pP->stat_tx_data_bytes += (data_pdu_size - pdu_remaining_size);
//pdu_p->sn = rlc_pP->vt_s; // set DATA/CONTROL field is DATA PDU(1)
pdu_p->b1 = pdu_p->b1 | 0x80; // DATA/CONTROL field is DATA PDU 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->b1 = pdu_p->b1 | (rlc_pP->vt_s >> 8);
pdu_p->b2 = rlc_pP->vt_s & 0xFF; pdu_p->b2 = rlc_pP->vt_s & 0xFF;
rlc_pP->vt_s = (rlc_pP->vt_s+1) & RLC_AM_SN_MASK; rlc_pP->vt_s = (rlc_pP->vt_s+1) & RLC_AM_SN_MASK;
...@@ -511,24 +525,28 @@ void rlc_am_segment_10 ( ...@@ -511,24 +525,28 @@ void rlc_am_segment_10 (
pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size; pdu_tb_req_p->tb_size = data_pdu_size - pdu_remaining_size;
//#warning "why 3000: changed to RLC_SDU_MAX_SIZE " //#warning "why 3000: changed to RLC_SDU_MAX_SIZE "
assert(pdu_tb_req_p->tb_size < RLC_SDU_MAX_SIZE ); assert(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); 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); //list_add_tail_eurecom (pdu_mem_p, &rlc_pP->segmentation_pdu_list);
pdu_mngt_p->mem_block = pdu_mem_p; pdu_mngt_p->mem_block = pdu_mem_p;
pdu_mngt_p->first_byte = (unsigned char*)pdu_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->header_and_payload_size = data_pdu_size - pdu_remaining_size;
pdu_mngt_p->retx_count = -1; 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);
rlc_pP->retrans_num_pdus += 1;
rlc_pP->retrans_num_bytes += pdu_mngt_p->header_and_payload_size;
//TBC: What for resetting local pointers at the end ??
pdu_p = NULL; pdu_p = NULL;
pdu_mem_p = NULL; pdu_mem_p = NULL;
//nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size; //nb_bytes_to_transmit = nb_bytes_to_transmit - data_pdu_size;
nb_bytes_to_transmit = 0; // 1 PDU only nb_bytes_to_transmit = 0; // 1 PDU only
mem_block_t* copy = rlc_am_retransmit_get_copy (ctxt_pP, rlc_pP, (rlc_pP->vt_s-1) & RLC_AM_SN_MASK); /* 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); list_add_tail_eurecom (copy, &rlc_pP->segmentation_pdu_list);
} }
......
...@@ -51,14 +51,14 @@ ...@@ -51,14 +51,14 @@
# endif # endif
# endif # endif
/*! \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) /*! \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,boolean_t is_new_pdu)
* \brief Set or not the poll bit in the PDU header depending on RLC AM protocol variables. * \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] ctxt_pP Running context.
* \param[in] rlcP RLC AM protocol instance pointer. * \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] 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. * \param[in] payload_sizeP Size of the payload of the PDU.
*/ */
protected_rlc_am_segment(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);) protected_rlc_am_segment(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,boolean_t is_new_pdu);)
/*! \fn void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP) /*! \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). * \brief Segment a PDU with 10 bits sequence number, based on segmentation information given by MAC (size to transmit).
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* @ingroup _rlc_am_internal_segment_impl_ * @ingroup _rlc_am_internal_segment_impl_
* @{ * @{
*/ */
#if 0
#ifndef __RLC_AM_SEGMENT_HOLES_H__ #ifndef __RLC_AM_SEGMENT_HOLES_H__
# define __RLC_AM_SEGMENT_HOLES_H__ # define __RLC_AM_SEGMENT_HOLES_H__
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -108,3 +108,4 @@ protected_rlc_am_segments_holes(void rlc_am_add_hole ( ...@@ -108,3 +108,4 @@ protected_rlc_am_segments_holes(void rlc_am_add_hole (
sdu_size_t so_stopP);) sdu_size_t so_stopP);)
/** @} */ /** @} */
#endif #endif
#endif
...@@ -70,6 +70,8 @@ rlc_am_check_timer_status_prohibit( ...@@ -70,6 +70,8 @@ rlc_am_check_timer_status_prohibit(
PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP));
//#warning TO DO rlc_am_check_timer_status_prohibit //#warning TO DO rlc_am_check_timer_status_prohibit
rlc_am_stop_and_reset_timer_status_prohibit(ctxt_pP, rlc_pP); 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; //rlc_pP->t_status_prohibit.frame_time_out = ctxt_pP->frame + rlc_pP->t_status_prohibit.time_out;
} }
} }
...@@ -110,6 +112,7 @@ rlc_am_start_timer_status_prohibit( ...@@ -110,6 +112,7 @@ rlc_am_start_timer_status_prohibit(
rlc_pP->t_status_prohibit.running = 1; 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_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_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", 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), PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
rlc_pP->t_status_prohibit.ms_time_out); rlc_pP->t_status_prohibit.ms_time_out);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment