- Fix: avoid infinite loop on mulitcast read thread if no data to read

Pre-ci test passed

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4000 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
Cedric Roux
2013-06-25 09:05:02 +00:00
commit 56c66c09aa
4111 changed files with 2133103 additions and 0 deletions
+103
View File
@@ -0,0 +1,103 @@
CC = gcc
SSE3PROC = $(shell echo `grep ssse3 /proc/cpuinfo`)
SSE4PROC = $(shell echo `grep sse4 /proc/cpuinfo`)
CPUFLAGS = -mmmx -msse -msse2 -m32 -mssse3 #-msse4
CPUFLAGS += $(shell if [ -z $$SSE3PROC]; then echo "" ; else echo "-mssse3"; fi)
CPUFLAGS += $(shell if [ -z $$SSE4PROC]; then echo "" ; else echo "-msse4"; fi)
cygwin = $(shell if [ $$OSTYPE = "cygwin" ] ; then echo "1" ; else echo "0" ; fi)
TOP_DIR = $(OPENAIR1_DIR)
OPENAIR1_TOP = $(OPENAIR1_DIR)
OPENAIR2_TOP = $(OPENAIR2_DIR)
OPENAIR3_TOP = $(OPENAIR3_DIR)
OPENAIR3 = $(OPENAIR3_DIR)
EXE_FILE_NAME = test_pdcp
CFLAGS = -Wall -fno-strict-aliasing -DPHYSIM -DNODE_RG -DUSER_MODE -DPC_TARGET -DPC_DSP -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DMAX_MODULES=1 -g -ggdb $(CPUFLAGS) -I/usr/include/X11 #-Wno-packed-bitfield-compat
ASN1_MSG_INC = $(OPENAIR2_DIR)/RRC/LITE/MESSAGES
CFLAGS += -DOPENAIR_LTE -DOPENAIR2 #-DOFDMA_ULSCH -DIFFT_FPGA -DIFFT_FPGA_UE
CFLAGS += -I/usr/include/libxml2 -lxml2
#CFLAGS += -DXFORMS
ifdef DEBUG_PHY
CFLAGS += -DDEBUG_PHY
endif
ifdef NAS_NETLINK
CFLAGS += -DNAS_NETLINK -DLINUX -DDEBUG_CONTROL
endif
CFLAGS += -DPHY_ABSTRACTION #-DEMIT_ASN_DEBUG=1
CFLAGS += $(shell if [ $$OSTYPE = "cygwin" ] ; then echo "-DCYGWIN" ; fi)
#include $(OPENAIR1_DIR)/PHY/Makefile.inc
#include $(OPENAIR1_DIR)/SCHED/Makefile.inc
EXTRA_CFLAGS += -DOPENAIR2
EXTRA_CFLAGS += -DASSERT
EXTRA_CFLAGS += -DNO_RRM
COMMON_DIR = $(OPENAIR2_TOP)/COMMON
L2_INTERFACE_DIR = $(OPENAIR2_TOP)/RRC/L2_INTERFACE
RLC_UM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/UM_v9.3.0
RLC_AM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/AM_v9.3.0
RLC_TM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/TM
RLC_DIR = $(OPENAIR2_TOP)/LAYER2/RLC
PDCP_DIR = $(OPENAIR2_TOP)/LAYER2/PDCP_v10.1.0
MEM_DIR = $(OPENAIR2_TOP)/UTIL/MEM
LIST_DIR = $(OPENAIR2_TOP)/UTIL/LISTS
MATH_DIR = $(OPENAIR2_TOP)/UTIL/MATH
TIMER_DIR = $(OPENAIR2_TOP)/UTIL/TIMER
PHY_INTERFACE_DIR = $(OPENAIR2_TOP)/PHY_INTERFACE
RRC_DIR = $(OPENAIR2_TOP)/RRC/LITE
L2_INTERFACE_DIR = $(OPENAIR2_TOP)/RRC/L2_INTERFACE
MAC_DIR = $(OPENAIR2_TOP)/LAYER2/MAC
LOG_DIR=$(OPENAIR2_TOP)/UTIL/LOG
OCG_DIR=$(OPENAIR2_TOP)/UTIL/OCG
OPT_DIR=$(OPENAIR2_TOP)/UTIL/OPT
SOURCES_L2 = $(LIST_DIR)/list.c
SOURCES_L2 += $(LIST_DIR)/list2.c
SOURCES_L2 += $(PDCP_DIR)/pdcp.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_primitives.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_sequence_manager.c
SOURCES_L2 += $(MEM_DIR)/mem_block.c
LOG_OBJS = $(LOG_DIR)/log.o
OPT_OBJS = $(OPT_DIR)/probe.o
L2_OBJS=$(addsuffix .o,$(basename $(SOURCES_L2))) $(PHY_INTERFACE_OBJS) $(MAC_OBJS) $(L2_INTERFACE_OBJS) $(RRC_OBJS) $(LOG_OBJS) $(OPT_OBJS)
L2_incl = -I$(OPENAIR2_TOP) -I$(COMMON_DIR) -I$(RLC_DIR) -I$(RLC_AM_DIR) -I$(RLC_UM_DIR) -I$(RLC_TM_DIR) -I$(PDCP_DIR) -I$(MEM_DIR) -I$(LIST_DIR) \
-I$(LOG_DIR) -I$(MATH_DIR) -I$(TIMER_DIR) -I$(OPENAIR3)/MESH -I$(OPENAIR2_TOP)/RRC/MESH -I$(OPENAIR2_TOP)/RRC/MESH/MESSAGES -I$(OPENAIR3)/MESH/RRM -I$(OPT_DIR) \
-I$(OCG_DIR)
ASN1_MSG_OBJS2 := $(foreach file, $(ASN1_MSG_OBJS), $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/$(file))
# Define object file directory for RLM code
RLC_OBJ_DIR = $(RLC_DIR)/*.o $(RLC_AM_DIR)/*.o $(RLC_UM_DIR)/*.o $(RLC_TM_DIR)/*.o
OBJ = $(PHY_OBJS) $(SIMULATION_OBJS) $(SCHED_OBJS) $(STATS_OBJS) $(ASN1_MSG_OBJS2) $(RLC_OBJ_DIR)
all: build_test_pdcp
$(OBJ) : %.o : %.c
$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $@ $<
$(L2_OBJS) : %.o : %.c
$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DMAC_CONTEXT=1 -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $@ $<
build_test_pdcp : $(OBJ) $(L2_OBJS) test_pdcp.c
echo CYGWIN variable is $(cygwin)
$(CC) test_pdcp.c -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $(EXE_FILE_NAME) $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(L2_OBJS) -lm -lcurses
clean:
rm -f test_pdcp
rm -f *.o
+184
View File
@@ -0,0 +1,184 @@
/*******************************************************************************
OPENAIRINTERFACE 0/1/2/3
Copyright(c) 1999 - 2011 EURECOM
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information:
Openair Admin <openair_admin@eurecom.fr>
Mailing List <openair_tech@eurecom.fr>
Forums http://forums.eurecom.fr/openairinterface
Eurecom, 2229, route des cretes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*________________________OEPNAIR/OPENAIR0/________________________
File : readme.txt
Authors : Baris Demiray
Company : EURECOM
Emails : baris.demiray@eurecom.fr
________________________________________________________________*/
-----------------
Table of contents
-----------------
The content of this readme is the following:
1) What is this block about in OpenAirInterface
2) Folders and files description
3) Organization of the folders and their dependancies
4) Makefile targets and how to build
4.1) NUMBER_OF_TEST_PACKETS
4.2) WINDOW_SIZE
4.3) TEST_RX_AND_TX_WINDOW
4.4) TEST_PDCP_DATA_REQUEST_AND_INDICATION
5) Compilation and running
6) How to use through a tutorial: run a simple experimentation
------------------------------------------------
1) What is this block about in OpenAirInterface?
------------------------------------------------
Code residing here is the test code for PDCP, particularly the
sequence numbering code, pdcp_data_req(), and pdcp_data_ind().
Sequence numbering code is at pdcp_sequence_number.{c|h}, pdcp_data_req()
and pdcp_data_ind() methods are in pdcp.{c|h}, all residing in PDCP_v10.1.0
directory at openair2/LAYER2/.
Normally, PDCP layer is in interaction with following layers,
+-----------+ +-----+
| IP Driver | | RRC |
+-----------+ +-----+
\ /
+--------+
| PDCP |
+--------+
|
+-----+
| RRC |
+-----+
But in this test PDCP is isolated (by the symbolic constant
PDCP_UNIT_TEST, defined in LAYER2/PDCP_v10.1.0/pdcp.h) from the rest of the
layers and tested on its own.
There are two different tests. First is for sequence numbers and the other is
for PDUs and relevant headers.
All the sections referred herein should be looked in 3GPP TS 36.323 V10.1.0
(2011-03).
--------------------------------
2) Folders and files description
--------------------------------
File/Folder Description
----------- -----------
- Makefile Build targets are `all` and `clean`
- test_pdcp.{c|h} Test code
- test_util.h Utility methods for debugging
- todo.txt Todo list
- with_rlc/ Test code to validate interface between PDCP and RLC
(written by Lionel)
-----------------------------------------------------
3) Organization of the folders and their dependancies
-----------------------------------------------------
There is only one subfolder named `with_rlc/` and it has no dependency with
other test code and has its own Makefile.
-------------------------------------
4) Makefile targets and how to build
-------------------------------------
There is only one build target named `build_test_pdcp` and it can be run
also through the target `all`.
To configure, there is a number of symbolic constants in test_pdcp.c.
---------------------------
4.1) NUMBER_OF_TEST_PACKETS
---------------------------
NUMBER_OF_TEST_PACKETS configures the number of packets that are to be
generated during the tests. For TX/RX window tests this is directly the
number of sequence numbers generated. For SDU test this constant determines
the number of packets passed to pdcp_data_req() (by test_pdcp_data_req()).
Then PDUs generated by PDCP are collected in a linked list and passed to
pdcp_data_ind() (by test_pdcp_data_ind()) for validation.
This value is currently set to 10000.
----------------
4.2) WINDOW_SIZE
----------------
This symbolic constant configures TX and RX window size.
Currently this value is set to 4096 in accordance with the size of sequence
number field (12 bits, see 6.2.3).
--------------------------
4.3) TEST_RX_AND_TX_WINDOW
--------------------------
Currently PDCP tests are performed either for TX/RX window or for PDUs
because PDCP states are not reset inbetween two tests. If this constant is
defined then only TX/RX tests are performed generating NUMBER_OF_TEST_PACKETS
packets.
Warning: If this and TEST_PDCP_DATA_REQUEST_AND_INDICATION are both defined
then secondly run test will fail.
------------------------------------------
4.4) TEST_PDCP_DATA_REQUEST_AND_INDICATION
------------------------------------------
Currently PDCP tests are performed either for TX/RX window or for PDUs
because PDCP states are not reset inbetween two tests. If this constant is
defined then only PDU test is performed generating NUMBER_OF_TEST_PACKETS
packets.
Warning: If this and TEST_RX_AND_TX_WINDOW are both defined then secondly run
test will fail.
--------------------------
5) Compilation and running
--------------------------
Since default target is `all` following command suffices,
$ make
To run,
$ ./test_pdcp
---------------------------------------------------------------
6) How to use through a tutorial: run a simple experimentation
---------------------------------------------------------------
Not applicable, see section 5.
+394
View File
@@ -0,0 +1,394 @@
/*
* PDCP test code
*
* Author: Baris Demiray <baris.demiray@eurecom.fr>
*/
#include "MAC_INTERFACE/vars.h"
#include "LAYER2/MAC/vars.h"
#include "UTIL/LOG/log_if.h"
#include "OCG_vars.h"
#include "test_util.h"
#include "test_pdcp.h"
/*
* These are the PDCP entities that will be utilised
* throughout the test
*
* For pdcp_data_req() and pdcp_data_ind() these
* are passed and used
*/
pdcp_t pdcp_array[2];
/*
* TX list is the one we use to receive PDUs created by pdcp_data_req() and
* RX list is the one we use to pass these PDUs to pdcp_data_ind(). In test_pdcp_data_req()
* method every PDU created by pdcp_data_req() are first validated and then added to RX
* list after it's removed from TX list
*/
list_t test_pdu_tx_list;
list_t test_pdu_rx_list;
/*
* This is used by a number of methods to determine how
* many times a packet should be generated/a test run
*/
#define NUMBER_OF_TEST_PACKETS 10000
/*
* This is determined by the size of Sequence Number
* field and used to check sequence number synchronisation
*/
#define WINDOW_SIZE 4096 // 12-bit SN
/*
* Test configuration is STATEFUL. If you want to run DATA_REQUEST after TX_WINDOW
* then you have to reset/reinitialize PDCP entity state!
*
* TEST_RX_AND_TX_WINDOW Tests TX window code by repetitively asking for new TX
* sequence numbers without generating any packets
* And tests RX window code by supplying sequenced RX sequence
* numbers and asking RX window code to validate, without
* generating any packets
*/
#define TEST_RX_AND_TX_WINDOW 0
/*
* TEST_PDCP_DATA_REQUEST_AND_INDICATION Tests pdcp_data_req() method by repetitively asking it
* to create a PDCP PDU out of supplied SDU and parsing
* particular fields of relevant PDU lateron
* Afterwards, those PDUs created by pdcp_data_req() are
* passed to pdcp_data_ind()
*/
#define TEST_PDCP_DATA_REQUEST_AND_INDICATION 1
/*
* Buffer content used for testing purposes
*/
#define DUMMY_BUFFER ((unsigned char*)"123456789")
#define DUMMY_BUFFER_SIZE 10
int main(int argc, char **argv) {
unsigned char index = 0;
unsigned char test_result = 0;
/*
* Initialize memory allocator, list_t for test PDUs, and log generator
*/
pool_buffer_init();
list_init(&test_pdu_tx_list, NULL);
list_init(&test_pdu_rx_list, NULL);
logInit();
if (init_pdcp_entity(&pdcp_array[0]) == TRUE && init_pdcp_entity(&pdcp_array[1]) == TRUE)
msg("[TEST] PDCP entity initialization OK\n");
else {
msg("[TEST] Cannot initialize PDCP entities!\n");
return 1;
}
/* Initialize PDCP state variables */
for (index = 0; index < 2; ++index) {
if (pdcp_init_seq_numbers(&pdcp_array[index]) == FALSE) {
msg("[TEST] Cannot initialize sequence numbers of PDCP entity %d!\n", index);
exit(1);
} else {
msg("[TEST] Sequence number state of PDCP entity %d is initialized\n", index);
}
}
#if TEST_RX_AND_TX_WINDOW
/* Test TX window */
if (test_tx_window() == FALSE)
test_result = 1;
/* Test RX window */
if (test_rx_window() == FALSE)
test_result = 1;
#endif
#if TEST_PDCP_DATA_REQUEST_AND_INDICATION
/* Test pdcp_data_req() method in pdcp.c */
if (test_pdcp_data_req() == FALSE)
test_result = 1;
/* Test pdcp_data_ind() method in pdcp.c */
if (test_pdcp_data_ind() == FALSE)
test_result = 1;
#endif
if (test_result) {
msg("\n\nOne or more tests failed!\n");
} else {
msg("\n\nAll tests are successfull!\n");
}
return test_result;
}
BOOL init_pdcp_entity(pdcp_t *pdcp_entity)
{
if (pdcp_entity == NULL)
return FALSE;
/*
* Initialize sequence number state variables of relevant PDCP entity
*/
pdcp_entity->next_pdcp_tx_sn = 0;
pdcp_entity->next_pdcp_rx_sn = 0;
pdcp_entity->tx_hfn = 0;
pdcp_entity->rx_hfn = 0;
/* SN of the last PDCP SDU delivered to upper layers */
pdcp_entity->last_submitted_pdcp_rx_sn = 4095;
pdcp_entity->seq_num_size = 12;
msg("PDCP entity is initialized: Next TX: %d, Next Rx: %d, TX HFN: %d, RX HFN: %d, " \
"Last Submitted RX: %d, Sequence Number Size: %d\n", pdcp_entity->next_pdcp_tx_sn, \
pdcp_entity->next_pdcp_rx_sn, pdcp_entity->tx_hfn, pdcp_entity->rx_hfn, \
pdcp_entity->last_submitted_pdcp_rx_sn, pdcp_entity->seq_num_size);
return TRUE;
}
BOOL test_tx_window()
{
unsigned long index = 0;
for (index = 0; index < NUMBER_OF_TEST_PACKETS; ++index) {
u16 pseudo_tx_sn = pdcp_get_next_tx_seq_number(&pdcp_array[0]);
if (pseudo_tx_sn == index % WINDOW_SIZE)
msg("TX packet # %07lu seq # %04d hfn # %04d\n", index, pseudo_tx_sn, pdcp_array[0].tx_hfn);
else {
msg("TX packet is out-of-window!\n");
return FALSE;
}
}
return TRUE;
}
BOOL test_rx_window()
{
unsigned long index = 0;
for (index = 0; index < NUMBER_OF_TEST_PACKETS; ++index) {
u16 pseudo_rx_sn = (index == 0) ? 0 : index % WINDOW_SIZE;
if (pdcp_is_rx_seq_number_valid(pseudo_rx_sn, &pdcp_array[1]) == TRUE) {
msg("RX packet # %07lu seq # %04d last-submitted # %04d hfn # %04d\n", \
index, pdcp_array[1].next_pdcp_rx_sn, pdcp_array[1].last_submitted_pdcp_rx_sn, pdcp_array[1].rx_hfn);
} else {
msg("RX packet seq # %04lu is not valid!\n", index);
return FALSE;
}
}
return TRUE;
}
BOOL test_pdcp_data_req()
{
unsigned char* pdcp_test_pdu_buffer = NULL;
unsigned char pdcp_test_pdu_buffer_size = DUMMY_BUFFER_SIZE + PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
unsigned int index = 0;
/*
* Create an unsigned char buffer out of mem_block_t
*/
pdcp_test_pdu_buffer = (unsigned char*) calloc(1, pdcp_test_pdu_buffer_size);
if (pdcp_test_pdu_buffer == NULL) {
msg("Cannot allocate a buffer for test!\n");
return FALSE;
}
/*
* Ask PDCP to handle a number of data requests
*/
for (index = 0; index < NUMBER_OF_TEST_PACKETS; ++index) {
msg("\n\nAsking PDCP to send %d/%d SDU...\n", index+1, NUMBER_OF_TEST_PACKETS);
/*
* Reset test pdu buffer for every run
*/
memset(pdcp_test_pdu_buffer, 0x00, pdcp_test_pdu_buffer_size);
/*
* Ask PDCP to create a PDU with given buffer and enqueue it to `test_pdu_tx_list`
*/
if (pdcp_data_req(0, 0, 10, DUMMY_BUFFER, &pdcp_array[0], &test_pdu_tx_list) == TRUE) {
msg("[TEST] Starting to dissect PDU created by PDCP...\n");
/*
* XXX mem_block_t doesn't hold buffer size, how do we keep the size
* information if we pass mem_block_ts via a linked list?
*/
#if 0
if (pdcp_test_pdu_buffer_size == 0 || pdcp_test_pdu_buffer == NULL) {
msg("[TEST] PDU created by pdcp_data_req() is invalid!\n");
return FALSE;
}
#endif
/*
* Serialize incoming mem_block_t into an unsigned character array
* and add removed PDU to RX list in order to use it in the next test
* (test_pdcp_data_ind())
*/
mem_block_t* pdcp_test_pdu = list_remove_head(&test_pdu_tx_list);
memcpy(pdcp_test_pdu_buffer, pdcp_test_pdu->data, pdcp_test_pdu_buffer_size);
list_add_tail_eurecom(pdcp_test_pdu, &test_pdu_rx_list);
/*
* Verify that this is a data packet by checking
* if the first bit is 0x00 (PDCP_DATA_PDU)
*/
if (pdcp_test_pdu_buffer[0] & 0x80) {
msg("[TEST] First bit is not 0, which means this is not a Data PDU!\n");
return FALSE;
} else {
msg("[TEST] First bit is 0 so this is a Data PDU, OK\n");
}
/*
* Verify that all three reserved bits are 0
*/
if ((pdcp_test_pdu_buffer[0] & 0x70) != 0) {
msg("[TEST] Reserved bits are not 0!\n");
return FALSE;
} else {
msg("[TEST] Reserved bits are all 0, OK\n");
}
/*
* Parse and verify sequence number
*/
u16 sequence_number = pdcp_get_sequence_number_of_pdu_with_long_sn(pdcp_test_pdu_buffer);
msg("[TEST] Parsed sequence number is %04d\n", sequence_number);
if (sequence_number != index % WINDOW_SIZE) {
msg("[TEST] Sequence numbers are out-of-order!\n");
return FALSE;
} else {
msg("[TEST] Sequence number is correct\n");
}
} else {
msg("[TEST] pdcp_data_req() returned FALSE!\n");
return FALSE;
}
}
return TRUE;
}
BOOL test_pdcp_data_ind()
{
/*
* This is the list that pdcp_data_ind() takes to put pdcp_data_ind_header_t
* packets after it receives/validates PDUs and preprends them with pdcp_data_ind_header_t
* structure. Here, after this list is filled by pdcp_data_ind() we parse/validate
* every single element in the list
*/
list_t test_pdu_indication_list;
mem_block_t* test_sdu = NULL;
/*
* pdcp_data_req() method prepended PDU header in front of DUMMY_BUFFER so
* the size should be 12 bytes
*/
unsigned char test_sdu_size = PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE + DUMMY_BUFFER_SIZE;
unsigned int index = 0;
/*
* Initialize linked list
*/
list_init(&test_pdu_indication_list, NULL);
/*
* Ask PDCP to handle a number of data indications
*/
msg("There are %d PDUs in the list\n", test_pdu_rx_list.nb_elements);
/*
* Traverse PDU list and pass each one of them to pdcp_data_ind()
*/
while (list_get_head(&test_pdu_rx_list) != NULL) {
msg("\n\nAsking PDCP to receive %d. SDU...\n", 1 + index++);
test_sdu = list_remove_head(&test_pdu_rx_list);
if (pdcp_data_ind(0, 0, test_sdu_size, test_sdu, &pdcp_array[0], &test_pdu_indication_list) == FALSE) {
msg("[TEST] pdcp_data_ind() failed to handle data indication!\n");
return FALSE;
} else {
msg("[TEST] pdcp_data_ind() succcessfuly handled data indication\n");
}
/*
* Parse/validate fields of SDU
*/
msg("[TEST] Starting to dissect SDU created by PDCP...\n");
/*
* Get pdcp_data_ind_header_t added by pdcp_data_ind()
*/
mem_block_t* test_data_ind_header = list_remove_head(&test_pdu_indication_list);
if (test_data_ind_header == NULL) {
msg("[TEST] Data indication header is not valid!\n");
return FALSE;
} else {
pdcp_data_ind_header_t* indication_header = (pdcp_data_ind_header_t*)test_data_ind_header->data;
/*
* Verify that radio bearer ID is correct (0)
*/
if (indication_header->rb_id == 0) {
msg("[TEST] Radio bearer ID is correct\n");
} else {
msg("[TEST] Radio bearer ID is not correct! (expected: 0, parsed: %d)\n", indication_header->rb_id);
return FALSE;
}
/*
* Verify that SDU size is correct (DUMMY_BUFFER_SIZE)
*/
if (indication_header->data_size == DUMMY_BUFFER_SIZE + PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE) {
msg("[TEST] SDU size is correct\n");
} else {
msg("[TEST] SDU size is not correct! (expected: %d, parsed: %d)\n", DUMMY_BUFFER_SIZE, indication_header->data_size);
return FALSE;
}
/*
* XXX Verify `indication_header->inst` when you know what it is
*/
}
/*
* XXX PDCP PDU header should also be checked here
*/
/*
* Verify that serialised data is the stream we've supplied
*
* Data comes after `pdcp_data_ind_header_t` and `pdcp_user_plane_data_pdu_header_with_long_sn`
*/
unsigned char data_index = sizeof(pdcp_data_ind_header_t) + PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
if (memcmp(DUMMY_BUFFER, (unsigned char*)&(test_data_ind_header->data[data_index]), DUMMY_BUFFER_SIZE) == 0) {
msg("[TEST] Data payload of pdcp_data_ind_header_t matches with the stream we sent\n");
} else {
msg("[TEST] Data payload of pdcp_data_ind_header_t does not match with the stream we sent!\n");
/*
* Print octets of both streams
* XXX This could be a method in test_util.h
*/
print_byte_stream("[TEST] TXed data: ", DUMMY_BUFFER, DUMMY_BUFFER_SIZE);
print_byte_stream("[TEST] RXed data: ", (unsigned char*)&(test_data_ind_header->data[data_index]), DUMMY_BUFFER_SIZE);
return FALSE;
}
}
return TRUE;
}
+37
View File
@@ -0,0 +1,37 @@
/*
* PDCP test code
*
* Author: Baris Demiray <baris.demiray@eurecom.fr>
*/
#ifndef TEST_PDCP_H
#define TEST_PDCP_H
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
#include "LAYER2/PDCP_v10.1.0/pdcp_primitives.h"
/*
* To suppress following errors
*
* /homes/demiray/workspace/openair4G/trunk/openair2/LAYER2/PDCP_v10.1.0/pdcp.o: In function `pdcp_run':
* /homes/demiray/workspace/openair4G/trunk/openair2/LAYER2/PDCP_v10.1.0/pdcp.c:270: undefined reference to `pdcp_fifo_read_input_sdus'
* /homes/demiray/workspace/openair4G/trunk/openair2/LAYER2/PDCP_v10.1.0/pdcp.c:273: undefined reference to `pdcp_fifo_flush_sdus'
*/
int pdcp_fifo_flush_sdus () { return 0; }
int pdcp_fifo_read_input_sdus_remaining_bytes () { return 0; }
int pdcp_fifo_read_input_sdus () { return 0; }
BOOL init_pdcp_entity(pdcp_t *pdcp_entity);
BOOL test_tx_window();
BOOL test_rx_window();
BOOL test_pdcp_data_req();
BOOL test_pdcp_data_ind();
/*
* PDCP methods that are going to be utilised throughout the test
*/
extern BOOL pdcp_init_seq_numbers(pdcp_t* pdcp_entity);
extern u16 pdcp_get_next_tx_seq_number(pdcp_t* pdcp_entity);
extern BOOL pdcp_is_rx_seq_number_valid(u16 seq_num, pdcp_t* pdcp_entity);
#endif
+77
View File
@@ -0,0 +1,77 @@
/*
* Helper methods for PDCP test code
*
* Author: Baris Demiray <baris.demiray@eurecom.fr>
*/
#ifndef TEST_UTIL_H
#define TEST_UTIL_H
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
/*
* Prints binary representation of given octet prepending
* passed log message
*
* @param Octet as an unsigned character
* @return None
*/
void print_binary_representation(unsigned char* message, unsigned char byte)
{
unsigned char index = 0;
unsigned char mask = 0x80;
if (message != NULL)
printf("%s", message);
for (index = 0; index < 8; ++index) {
if (byte & mask) printf("1");
else printf("0");
mask /= 2;
}
printf("\n");
}
/*
* Prints octets of a byte array in hexadecimal representation
*/
void print_byte_stream(char* message, unsigned char* buffer, unsigned long size)
{
if (buffer == NULL)
return;
unsigned long index = 0lu;
printf("%s", message);
for (index = 0; index < size; ++index) {
msg("%x ", buffer[index]);
}
msg("\n");
}
/*
* Prints PDCP properties
*
* @param pdcp_t pointer for relevant PDCP entity
* @return none
*/
void print_pdcp_properties(pdcp_t* pdcp_entity)
{
printf("PDCP properties:\n");
if (pdcp_entity == NULL) {
printf("PDCP pointer is invalid!\n");
} else {
printf("-> Is header compression active? %s\n", ((pdcp_entity->header_compression_active == TRUE) ? "Yes" : "No"));
printf("-> Sequence number size: %d bits\n", pdcp_entity->seq_num_size);
printf("-> Next TX sequence number: %d\n", pdcp_entity->next_pdcp_tx_sn);
printf("-> Next RX sequence number: %d\n", pdcp_entity->next_pdcp_rx_sn);
printf("-> TX HFN: %d\n", pdcp_entity->tx_hfn);
printf("-> RX HFN: %d\n", pdcp_entity->rx_hfn);
printf("-> Last submitted RX sequence number: %d\n", pdcp_entity->last_submitted_pdcp_rx_sn);
}
}
#endif
+7
View File
@@ -0,0 +1,7 @@
* Test configuration should be configurable on run-time (command-line?)
* Inbetween every test PDCP entity should be reinitialized or different
PDCP entities should be utilised
baris.demiray@eurecom.fr
+141
View File
@@ -0,0 +1,141 @@
CC = gcc
SSE3PROC = $(shell echo `grep ssse3 /proc/cpuinfo`)
SSE4PROC = $(shell echo `grep sse4 /proc/cpuinfo`)
CPUFLAGS = -mmmx -msse -msse2 -m32 -mssse3 #-msse4
CPUFLAGS += $(shell if [ -z $$SSE3PROC]; then echo "" ; else echo "-mssse3"; fi)
CPUFLAGS += $(shell if [ -z $$SSE4PROC]; then echo "" ; else echo "-msse4"; fi)
cygwin = $(shell if [ $$OSTYPE = "cygwin" ] ; then echo "1" ; else echo "0" ; fi)
TOP_DIR = $(OPENAIR1_DIR)
OPENAIR1_TOP = $(OPENAIR1_DIR)
OPENAIR2_TOP = $(OPENAIR2_DIR)
OPENAIR3_TOP = $(OPENAIR3_DIR)
OPENAIR3 = $(OPENAIR3_DIR)
EXE_FILE_NAME = test_pdcp_rlc
CFLAGS = -Wall -fno-strict-aliasing -DPHYSIM -DNODE_RG -DUSER_MODE -DPC_TARGET -DPC_DSP -DNB_ANTENNAS_RX=2 -DNB_ANTENNAS_TXRX=2 -DNB_ANTENNAS_TX=2 -DMAX_MODULES=1 -g -ggdb $(CPUFLAGS) -I/usr/include/X11 #-Wno-packed-bitfield-compat
ASN1_MSG_INC = $(OPENAIR2_DIR)/RRC/LITE/MESSAGES
CFLAGS += -DOPENAIR_LTE -DOPENAIR2 #-DOFDMA_ULSCH -DIFFT_FPGA -DIFFT_FPGA_UE
CFLAGS += -I/usr/include/libxml2 -lxml2
#CFLAGS += -DXFORMS
ifdef DEBUG_PHY
CFLAGS += -DDEBUG_PHY
endif
ifdef NAS_NETLINK
CFLAGS += -DNAS_NETLINK -DLINUX -DDEBUG_CONTROL
endif
CFLAGS += -DPHY_ABSTRACTION #-DEMIT_ASN_DEBUG=1
CFLAGS += $(shell if [ $$OSTYPE = "cygwin" ] ; then echo "-DCYGWIN" ; fi)
#include $(OPENAIR1_DIR)/PHY/Makefile.inc
#include $(OPENAIR1_DIR)/SCHED/Makefile.inc
EXTRA_CFLAGS += -DOPENAIR2
EXTRA_CFLAGS += -DASSERT
EXTRA_CFLAGS += -DNO_RRM
COMMON_DIR = $(OPENAIR2_TOP)/COMMON
L2_INTERFACE_DIR = $(OPENAIR2_TOP)/RRC/L2_INTERFACE
RLC_UM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/UM_v9.3.0
RLC_AM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/AM_v9.3.0
RLC_TM_DIR = $(OPENAIR2_TOP)/LAYER2/RLC/TM
RLC_DIR = $(OPENAIR2_TOP)/LAYER2/RLC
PDCP_DIR = $(OPENAIR2_TOP)/LAYER2/PDCP_v10.1.0
MEM_DIR = $(OPENAIR2_TOP)/UTIL/MEM
LIST_DIR = $(OPENAIR2_TOP)/UTIL/LISTS
MATH_DIR = $(OPENAIR2_TOP)/UTIL/MATH
TIMER_DIR = $(OPENAIR2_TOP)/UTIL/TIMER
PHY_INTERFACE_DIR = $(OPENAIR2_TOP)/PHY_INTERFACE
RRC_DIR = $(OPENAIR2_TOP)/RRC/LITE
L2_INTERFACE_DIR = $(OPENAIR2_TOP)/RRC/L2_INTERFACE
MAC_DIR = $(OPENAIR2_TOP)/LAYER2/MAC
LOG_DIR=$(OPENAIR2_TOP)/UTIL/LOG
OCG_DIR=$(OPENAIR2_TOP)/UTIL/OCG
OPT_DIR=$(OPENAIR2_TOP)/UTIL/OPT
SOURCES_L2 = $(LIST_DIR)/list.c
SOURCES_L2 += $(LIST_DIR)/list2.c
SOURCES_L2 += $(PDCP_DIR)/pdcp.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_primitives.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_sequence_manager.c
SOURCES_L2 += $(RLC_DIR)/rlc_mac.c
SOURCES_L2 += $(RLC_DIR)/rlc.c
SOURCES_L2 += $(RLC_DIR)/rlc_rrc.c
SOURCES_L2 += $(RLC_DIR)/rlc_mpls.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_control_primitives.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_dar.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_fsm.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_reassembly.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_receiver.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_segment.c
SOURCES_L2 += $(RLC_UM_DIR)/rlc_um_test.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_init.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_timer_poll_retransmit.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_timer_reordering.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_timer_status_prohibit.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_segment.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_segments_holes.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_in_sdu.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_receiver.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_retransmit.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_windows.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_rx_list.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_reassembly.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_status_report.c
SOURCES_L2 += $(RLC_TM_DIR)/rlc_tm.c
SOURCES_L2 += $(RLC_TM_DIR)/rlc_tm_control_primitives.c
SOURCES_L2 += $(RLC_TM_DIR)/rlc_tm_fsm.c
SOURCES_L2 += $(RLC_TM_DIR)/rlc_tm_segment.c
SOURCES_L2 += $(RLC_TM_DIR)/rlc_tm_reassembly.c
SOURCES_L2 += $(MEM_DIR)/mem_block.c
LOG_OBJS = $(LOG_DIR)/log.o
OPT_OBJS = $(OPT_DIR)/probe.o
L2_OBJS=$(addsuffix .o,$(basename $(SOURCES_L2))) $(PHY_INTERFACE_OBJS) $(MAC_OBJS) $(L2_INTERFACE_OBJS) $(RRC_OBJS) $(LOG_OBJS) $(OPT_OBJS)
L2_incl = -I$(OPENAIR2_TOP) -I$(COMMON_DIR) -I$(RLC_DIR) -I$(RLC_AM_DIR) -I$(RLC_UM_DIR) -I$(RLC_TM_DIR) -I$(PDCP_DIR) -I$(MEM_DIR) -I$(LIST_DIR) \
-I$(LOG_DIR) -I$(MATH_DIR) -I$(TIMER_DIR) -I$(OPENAIR3)/MESH -I$(OPENAIR2_TOP)/RRC/MESH -I$(OPENAIR2_TOP)/RRC/MESH/MESSAGES -I$(OPENAIR3)/MESH/RRM -I$(OPT_DIR) \
-I$(OCG_DIR)
ASN1_MSG_OBJS2 := $(foreach file, $(ASN1_MSG_OBJS), $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/$(file))
# Define object file directory for RLM code
#RLC_OBJ_DIR = $(RLC_DIR)/*.o $(RLC_AM_DIR)/*.o $(RLC_UM_DIR)/*.o $(RLC_TM_DIR)/*.o
OBJ = $(PHY_OBJS) $(SIMULATION_OBJS) $(SCHED_OBJS) $(STATS_OBJS) $(ASN1_MSG_OBJS2) $(RLC_OBJ_DIR)
all: build_test_pdcp_rlc
$(OBJ) : %.o : %.c
$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $@ $<
$(L2_OBJS) : %.o : %.c
$(CC) -c $(CFLAGS) $(EXTRA_CFLAGS) -DMAC_CONTEXT=1 -DPHY_CONTEXT=1 -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $@ $<
build_test_pdcp_rlc : $(OBJ) $(L2_OBJS) test_pdcp_rlc.c
echo CYGWIN variable is $(cygwin)
$(CC) test_pdcp_rlc.c -I$(TOP_DIR) $(L2_incl) -I$(ASN1_MSG_INC) -o $(EXE_FILE_NAME) $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(L2_OBJS) -lm -lcurses
clean:
rm -f test_pdcp_rlc
rm -f *.o
+59
View File
@@ -0,0 +1,59 @@
#----------------------------------------------------------------------------------------------------------------
The aim of the test code test_pdcp_rlc.c is primarily to test a PDCP protocol entity integrated with RLC layer.
This is a first step, in near future, this test may be extended with an other type of RLC (AM), and may be
integrated with the upcoming traffic generator.
#----------------------------------------------------------------------------------------------------------------
The code implements the following figure:
#----------------------------------------------------------------------------------------------------------------
+-+-+-+-+ +-+-+-+-+
| PDCP1 | | PDCP2 |
+-+-+-+-+ +-+-+-+-+
| |
+-+-+-+-+ +-+-+-+-+
| RLC1 | | RLC2 |
| UM | | UM |
+-+-+-+-+ +-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| MAC LAYER EMULATION |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#----------------------------------------------------------------------------------------------------------------
Compilation of the code:
#----------------------------------------------------------------------------------------------------------------
make -f Makefile.data_bearer
#----------------------------------------------------------------------------------------------------------------
Execution of the code:
#----------------------------------------------------------------------------------------------------------------
./test_pdcp_rlc
#----------------------------------------------------------------------------------------------------------------
What Could Be Frequently Asked Questions:
#----------------------------------------------------------------------------------------------------------------
#-------------------
Q:How to send a SDU?
A:
pdcp_rlc_test_send_sdu(0, 1, 2); // prototype pdcp_rlc_test_send_sdu(module_id_t module_idP, rb_id_t rab_idP, int sdu_indexP)
#-------------------
Q:How to fix the bitrate of the radio bearer?
A:
pdcp_rlc_test_exchange_pdus(&rlc[0].m_rlc_um_array[rlc[0].m_rlc_pointer[1].rlc_index],
&rlc[1].m_rlc_um_array[rlc[1].m_rlc_pointer[1].rlc_index],
1000,
1000);
Prototype:
pdcp_rlc_test_exchange_pdus(rlc_um_entity_t *um1P, // RLC UM instance 1
rlc_um_entity_t *um2P, // RLC UM instance 2
u16_t bytes_tx1P, // tx bytes requested at RLC UM instance 1 and sent to RLC UM instance 2
u16_t bytes_tx2P) // tx bytes requested at RLC UM instance 2 and sent to RLC UM instance 1
+270
View File
@@ -0,0 +1,270 @@
#define PDCP_C
#include <string.h>
#include <math.h>
#include <unistd.h>
#include "SIMULATION/TOOLS/defs.h"
#include "SIMULATION/RF/defs.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "PHY/vars.h"
#include "MAC_INTERFACE/vars.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
#include "UTIL/LOG/log_if.h"
#include "UTIL/LOG/log_extern.h"
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"
#include "UTIL/OCG/OCG.h"
#include "LAYER2/PDCP_v10.1.0/pdcp.h"
#include "OCG_vars.h"
#include "rlc.h"
#include "pdcp.h"
#define TEST_MAX_SEND_SDU 8192
#define TARGET_MAX_RX_ERROR_RATE 10
#define TARGET_MAX_TX_ERROR_RATE 10
static int g_error_on_phy = 0;
static int g_random_sdu;
static int g_random_nb_frames;
static int g_random_tx_pdu_size;
static int g_random_rx_pdu_size;
static int g_target_tx_error_rate;
static int g_target_rx_error_rate;
static int g_tx_packets = 0;
static int g_dropped_tx_packets = 0;
static int g_rx_packets = 0;
static int g_dropped_rx_packets = 0;
static int g_drop_rx = 0;
static int g_drop_tx = 0;
static int g_send_sdu_ids[TEST_MAX_SEND_SDU][2];
static int g_send_id_write_index[2];
static int g_send_id_read_index[2];
static s8_t *g_sdus[] = {"En dépit de son volontarisme affiché, le premier ministre est de plus en plus décrié pour son incompétence. La tension politique et dans l'opinion publique est encore montée d'un cran au Japon, sur fond d'inquiétantes nouvelles, avec du plutonium détecté dans le sol autour de la centrale de Fukushima. Le premier ministre Naoto Kan a solennellement déclaré que son gouvernement était «en état d'alerte maximum». Tout en reconnaissant que la situation restait «imprévisible». Ce volontarisme affiché par le premier ministre - que Nicolas Sarkozy rencontrera demain lors d'une visite au Japon - ne l'a pas empêché d'être la cible de violentes critiques de la part de parlementaires sur sa gestion de la crise. Attaqué sur le manque de transparence, il a assuré qu'il rendait publiques toutes les informations en sa possession. Un député de l'opposition, Yosuke Isozaki, a aussi reproché à Naoto Kan de ne pas avoir ordonné l'évacuation des populations dans la zone comprise entre 20 et 30 km autour de la centrale. «Peut-il y avoir quelque chose de plus irresponsable que cela ?», a-t-il lancé. Pour l'heure, la zone d'évacuation est limitée à un rayon de 20 km, seul le confinement étant recommandé pour les 10 km suivants. Sur ce sujet, les autorités japonaises ont été fragilisées mardi par les déclarations de Greenpeace, affirmant que ses experts avaient détecté une radioactivité dangereuse à 40 km de la centrale. L'organisation écologiste a appelé à une extension de la zone d'évacuation, exhortant Tokyo à «cesser de privilégier la politique aux dépens de la science». L'Agence japonaise de sûreté nucléaire a balayé ces critiques.",
"La pâquerette (Bellis perennis) est une plante vivace des prés, des pelouses, des bords de chemins et des prairies, haute de dix à vingt centimètres, de la famille des Astéracées, dont les fleurs naissent sur des inflorescences appelées capitules : celles du pourtour, que l'on croit à tort être des pétales, appelées fleurs ligulées, parce qu'elles ont la forme d'une languette, ou demi-fleurons, sont des fleurs femelles, dont la couleur varie du blanc au rose plus ou moins prononcé ; celles du centre, jaunes, appelées fleurs tubuleuses, parce que leur corolle forme un tube, ou fleurons, sont hermaphrodites. Ainsi, contrairement à l'opinion populaire, ce qu'on appelle une « fleur » de pâquerette n'est en réalité pas « une » fleur mais un capitule portant des fleurs très nombreuses.Leurs fruits s'envolent grâce au vent et dégagent des odeurs qui attirent les insectes.Une variété muricole peut pousser sur des murs humides verticaux.Les pâquerettes sont des fleurs rustiques et très communes en Europe, sur les gazons, les prairies, les chemins et les zones d'herbe rase.Elles ont la particularité, comme certaines autres fleurs de plantes herbacées, de se fermer la nuit et de s'ouvrir le matin pour s'épanouir au soleil ; elles peuvent aussi se fermer pendant les averses, voire un peu avant, ce qui permet dans les campagnes de prédire la pluie légèrement à l'avance.",
"La pâquerette",
" (Bellis perennis)",
" est une plante vivace des prés,",
" des pelouses,",
" des bords de chemins et des prairies,",
"haute de dix à",
" vingt centimètres",
", de la",
" famille des",
" Astéracées",
", dont",
" les",
" fleurs",
" naissent",
" sur",
" des",
" inflorescences",
" appelées",
" capitules",
" : celles",
" du pourtour",
", que l'on",
" croit à",
" tort",
" être",
" des pétales",
", appelées",
" fleurs ligulées",
", parce qu'elles",
" ont la forme d'une languette, ou demi-fleurons, sont",
" des fleurs femelles,",
" dont la couleur varie du blanc au rose plus ou moins prononcé ; celles du centre, jaunes,",
" appelées ",
"fleurs tubuleuses",
", parce que leur corolle forme un tube, ou fleurons, sont hermaphrodites."
};
int pdcp_fifo_flush_sdus () {}
int pdcp_fifo_read_input_sdus_remaining_bytes () {}
int pdcp_fifo_read_input_sdus () {}
BOOL init_pdcp_entity(pdcp_t *pdcp_entity);
//-----------------------------------------------------------------------------
void pdcp_rlc_test_mac_rlc_loop (struct mac_data_ind *data_indP, struct mac_data_req *data_requestP, int* drop_countP, int *tx_packetsP, int* dropped_tx_packetsP) //-----------------------------------------------------------------------------
{
mem_block_t* tb_src;
mem_block_t* tb_dst;
unsigned int tb_size;
data_indP->no_tb = 0;
while (data_requestP->data.nb_elements > 0) {
tb_src = list_remove_head (&data_requestP->data);
if (tb_src != NULL) {
tb_size = ((struct mac_tb_req *) (tb_src->data))->tb_size_in_bits >> 3;
printf("[RLC-LOOP] FOUND TB SIZE IN BITS %d IN BYTES %d sizeof (mac_rlc_max_rx_header_size_t) %d\n",
((struct mac_tb_req *) (tb_src->data))->tb_size_in_bits,
tb_size, sizeof (mac_rlc_max_rx_header_size_t));
*tx_packetsP = *tx_packetsP + 1;
if (*drop_countP == 0) {
tb_dst = get_free_mem_block(sizeof (mac_rlc_max_rx_header_size_t) + tb_size);
if (tb_dst != NULL) {
((struct mac_tb_ind *) (tb_dst->data))->first_bit = 0;
((struct mac_tb_ind *) (tb_dst->data))->data_ptr = &tb_dst->data[sizeof (mac_rlc_max_rx_header_size_t)];
((struct mac_tb_ind *) (tb_dst->data))->size = tb_size;
((struct mac_tb_ind *) (tb_dst->data))->error_indication = 0;
memcpy(((struct mac_tb_ind *) (tb_dst->data))->data_ptr,
&((struct mac_tb_req *) (tb_src->data))->data_ptr[0],
tb_size);
list_add_tail_eurecom(tb_dst, &data_indP->data);
data_indP->no_tb += 1;
} else {
printf("Out of memory error\n");
exit(-1);
}
} else {
printf("[RLC-LOOP] DROPPING 1 TB\n");
*drop_countP = *drop_countP - 1;
*dropped_tx_packetsP = *dropped_tx_packetsP + 1;
}
free_mem_block(tb_src);
if (data_indP->no_tb > 0) {
printf("[RLC-LOOP] Exchange %d TBs\n",data_indP->no_tb);
}
}
}
}
//-----------------------------------------------------------------------------
void pdcp_rlc_test_exchange_pdus(rlc_um_entity_t *um_txP,
rlc_um_entity_t *um_rxP,
u16_t bytes_txP,
u16_t bytes_rxP)
//-----------------------------------------------------------------------------
{
struct mac_data_req data_request_tx;
struct mac_data_req data_request_rx;
struct mac_data_ind data_ind_tx;
struct mac_data_ind data_ind_rx;
struct mac_status_ind tx_status;
struct mac_status_resp mac_rlc_status_resp_tx;
struct mac_status_resp mac_rlc_status_resp_rx;
memset(&data_request_tx, 0, sizeof(struct mac_data_req));
memset(&data_request_rx, 0, sizeof(struct mac_data_req));
memset(&data_ind_tx, 0, sizeof(struct mac_data_ind));
memset(&data_ind_rx, 0, sizeof(struct mac_data_ind));
memset(&tx_status, 0, sizeof(struct mac_status_ind));
memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, bytes_txP, tx_status);
data_request_tx = rlc_um_mac_data_request(um_txP);
mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, bytes_rxP, tx_status);
data_request_rx = rlc_um_mac_data_request(um_rxP);
pdcp_rlc_test_mac_rlc_loop(&data_ind_rx, &data_request_tx, &g_drop_tx, &g_tx_packets, &g_dropped_tx_packets);
pdcp_rlc_test_mac_rlc_loop(&data_ind_tx, &data_request_rx, &g_drop_rx, &g_rx_packets, &g_dropped_rx_packets);
rlc_um_mac_data_indication(um_rxP, data_ind_rx);
rlc_um_mac_data_indication(um_txP, data_ind_tx);
mac_xface->frame += 1;
//rlc_um_tx_buffer_display(um_txP,NULL);
//assert(um_txP->t_status_prohibit.time_out != 1);
//assert(um_rxP->t_status_prohibit.time_out != 1);
//assert(!((um_txP->vt_a == 954) && (um_txP->vt_us == 53)));
//assert(mac_xface->frame <= 151);
//check_mem_area(NULL);
//display_mem_load();
}
//-----------------------------------------------------------------------------
void pdcp_rlc_test_send_sdu(module_id_t module_idP, rb_id_t rab_idP, int sdu_indexP)
//-----------------------------------------------------------------------------
{
pdcp_data_req(module_idP, rab_idP, strlen(g_sdus[sdu_indexP]) + 1, g_sdus[sdu_indexP]);
}
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
//-----------------------------------------------------------------------------
{
unsigned long index = 0;
rlc_op_status_t rlc_op_status;
rlc_info_t rlc_info;
char * g_log_level = "trace"; // by default global log level is set to trace
mac_xface = malloc(sizeof(MAC_xface));
Mac_rlc_xface = (MAC_RLC_XFACE*)malloc16(sizeof(MAC_RLC_XFACE));
rlc_module_init ();
pdcp_module_init();
logInit();
if (init_pdcp_entity(&pdcp_array[0][1]) == TRUE && init_pdcp_entity(&pdcp_array[1][1]) == TRUE)
msg("PDCP entity initialization OK\n");
else {
msg("Cannot initialize PDCP entities!\n");
return 1;
}
/* Initialize PDCP state variables */
for (index = 0; index < 2; ++index) {
if (pdcp_init_seq_numbers(&pdcp_array[index][1]) == FALSE) {
msg("Cannot initialize %s PDCP entity!\n", ((index == 0) ? "first" : "second"));
exit(1);
}
}
/* Configure RLCs */
rlc_info.rlc_mode = RLC_UM;
rlc_info.rlc.rlc_um_info.timer_reordering = 20;
rlc_info.rlc.rlc_um_info.sn_field_length = 10;
rlc_info.rlc.rlc_um_info.is_mXch = 0;
rlc_op_status = rrc_rlc_config_req (0, ACTION_ADD, 1, RADIO_ACCESS_BEARER, rlc_info);
assert(rlc_op_status == RLC_OP_STATUS_OK);
rlc_op_status = rrc_rlc_config_req (1, ACTION_ADD, 1, RADIO_ACCESS_BEARER, rlc_info);
assert(rlc_op_status == RLC_OP_STATUS_OK);
/* Simulate data traffic */
pdcp_rlc_test_send_sdu(0, 1, 2);
pdcp_rlc_test_exchange_pdus(&rlc[0].m_rlc_um_array[rlc[0].m_rlc_pointer[1].rlc_index],
&rlc[1].m_rlc_um_array[rlc[1].m_rlc_pointer[1].rlc_index],
1000,
1000);
pdcp_rlc_test_exchange_pdus(&rlc[1].m_rlc_um_array[rlc[1].m_rlc_pointer[1].rlc_index],
&rlc[0].m_rlc_um_array[rlc[0].m_rlc_pointer[1].rlc_index],
1000,
1000);
return 0;
}
//-----------------------------------------------------------------------------
BOOL init_pdcp_entity(pdcp_t *pdcp_entity)
//-----------------------------------------------------------------------------
{
if (pdcp_entity == NULL)
return FALSE;
/*
* Initialize sequence number state variables of relevant PDCP entity
*/
pdcp_entity->next_pdcp_tx_sn = 0;
pdcp_entity->next_pdcp_rx_sn = 0;
pdcp_entity->tx_hfn = 0;
pdcp_entity->rx_hfn = 0;
/* SN of the last PDCP SDU delivered to upper layers */
pdcp_entity->last_submitted_pdcp_rx_sn = 4095;
pdcp_entity->seq_num_size = 12;
return TRUE;
}