- Added thread that fetch netlink packets and place them in a FIFO (option enabled by default) to reduce pdcp_run execution time
- Fix some debug formats git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4187 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -169,7 +169,8 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne
|
||||
return(dlsch);
|
||||
}
|
||||
}
|
||||
msg("new_eNB_dlsch exit flag %d, size of %d\n",exit_flag, sizeof(LTE_eNB_DLSCH_t));
|
||||
LOG_D(PHY, "new_eNB_dlsch exit flag %d, size of %ld\n",
|
||||
exit_flag, sizeof(LTE_eNB_DLSCH_t));
|
||||
free_eNB_dlsch(dlsch);
|
||||
return(NULL);
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_ite
|
||||
if (exit_flag==0)
|
||||
return(dlsch);
|
||||
}
|
||||
msg("new_ue_dlsch with size %d: exit_flag = %d\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
|
||||
msg("new_ue_dlsch with size %zu: exit_flag = %u\n",sizeof(LTE_DL_UE_HARQ_t), exit_flag);
|
||||
free_ue_dlsch(dlsch);
|
||||
|
||||
return(NULL);
|
||||
|
||||
@@ -43,11 +43,13 @@ int netlink_init(void)
|
||||
}
|
||||
printf("[NETLINK]Opened socket with fd %d\n",nas_sock_fd);
|
||||
|
||||
#if !defined(ENABLE_PDCP_NETLINK_FIFO)
|
||||
ret = fcntl(nas_sock_fd,F_SETFL,O_NONBLOCK);
|
||||
if (ret == -1) {
|
||||
printf("[NETLINK] Error fcntl (%d:%s)\n",errno, strerror(errno));
|
||||
// exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&nas_src_addr, 0, sizeof(nas_src_addr));
|
||||
nas_src_addr.nl_family = AF_NETLINK;
|
||||
|
||||
@@ -27,6 +27,7 @@ SOURCES_L2 += $(PDCP_DIR)/pdcp_sequence_manager.c
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp_primitives.c
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp_util.c
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp_security.c
|
||||
SOURCES_L2 += $(PDCP_DIR)/pdcp_netlink.c
|
||||
|
||||
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am.c
|
||||
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_init.c
|
||||
|
||||
@@ -82,8 +82,8 @@ extern int otg_rx_pkt( int src, int dst, int ctime, char *buffer_tx, unsigned in
|
||||
BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, sdu_size_t sdu_buffer_size, \
|
||||
unsigned char* sdu_buffer, pdcp_t* test_pdcp_entity, list_t* test_list)
|
||||
#else
|
||||
BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, u32 muiP, u32 confirmP, \
|
||||
sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer, u8 mode)
|
||||
BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb_id, u32 muiP, u32 confirmP, \
|
||||
sdu_size_t sdu_buffer_size, unsigned char* sdu_buffer, u8 mode)
|
||||
#endif
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -126,7 +126,7 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
memcpy(&pdcp_pdu->data[0], sdu_buffer, sdu_buffer_size);
|
||||
rlc_status = rlc_data_req(module_id, frame, eNB_flag, RLC_MBMS_YES, rb_id, muiP, confirmP, sdu_buffer_size, pdcp_pdu);
|
||||
} else
|
||||
rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
rlc_status = RLC_OP_STATUS_OUT_OF_RESSOURCES;
|
||||
} else {
|
||||
// calculate the pdcp header and trailer size
|
||||
if ((rb_id % NB_RB_MAX) < DTCH) {
|
||||
@@ -137,15 +137,15 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
pdcp_tailer_len = 0;
|
||||
}
|
||||
pdcp_pdu_size= sdu_buffer_size + pdcp_header_len + pdcp_tailer_len;
|
||||
|
||||
|
||||
LOG_I(PDCP, "Data request notification for PDCP entity with module ID %d and radio bearer ID %d pdu size %d (header%d, trailer%d)\n", module_id, rb_id,pdcp_pdu_size, pdcp_header_len,pdcp_tailer_len);
|
||||
|
||||
|
||||
/*
|
||||
* Allocate a new block for the new PDU (i.e. PDU header and SDU payload)
|
||||
*/
|
||||
LOG_D(PDCP, "Asking for a new mem_block of size %d\n", pdcp_pdu_size);
|
||||
pdcp_pdu = get_free_mem_block(pdcp_pdu_size);
|
||||
|
||||
|
||||
if (pdcp_pdu != NULL) {
|
||||
/*
|
||||
* Create a Data PDU with header and append data
|
||||
@@ -295,7 +295,7 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
"ID %d and radio bearer ID %d rlc sdu size %d eNB_flag %d\n", module_id, rb_id, sdu_buffer_size, eNB_flag);
|
||||
|
||||
if (sdu_buffer_size == 0) {
|
||||
LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!");
|
||||
LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -469,14 +469,13 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
pdcp_run (u32_t frame, u8 eNB_flag, u8 UE_index, u8 eNB_index) {
|
||||
void pdcp_run (u32_t frame, u8 eNB_flag, u8 UE_index, u8 eNB_index) {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef NAS_NETLINK
|
||||
#ifdef USER_MODE
|
||||
#define PDCP_DUMMY_BUFFER_SIZE 38
|
||||
unsigned char pdcp_dummy_buffer[PDCP_DUMMY_BUFFER_SIZE];
|
||||
unsigned char pdcp_dummy_buffer[PDCP_DUMMY_BUFFER_SIZE];
|
||||
#endif
|
||||
#endif
|
||||
// unsigned int diff, i, k, j;
|
||||
@@ -487,7 +486,7 @@ void
|
||||
// int pkt_size=0;
|
||||
// unsigned int ctime=0;
|
||||
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_IN);
|
||||
|
||||
/*
|
||||
if ((frame % 128) == 0) {
|
||||
@@ -510,10 +509,10 @@ void
|
||||
pdcp_fifo_read_input_sdus_from_otg(frame, eNB_flag, UE_index, eNB_index);
|
||||
|
||||
// IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
|
||||
pdcp_fifo_read_input_sdus(frame,eNB_flag);
|
||||
pdcp_fifo_read_input_sdus(frame, eNB_flag, UE_index, eNB_index);
|
||||
|
||||
// PDCP -> NAS/IP traffic: RX
|
||||
pdcp_fifo_flush_sdus(frame,eNB_flag);
|
||||
pdcp_fifo_flush_sdus(frame, eNB_flag);
|
||||
|
||||
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_RUN, VCD_FUNCTION_OUT);
|
||||
}
|
||||
@@ -531,21 +530,21 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
#endif
|
||||
){
|
||||
|
||||
long int rb_id = 0;
|
||||
long int lc_id = 0;
|
||||
long int srb_id = 0;
|
||||
long int rb_id = 0;
|
||||
long int lc_id = 0;
|
||||
long int srb_id = 0;
|
||||
long int mch_id = 0;
|
||||
rlc_mode_t rlc_type = RLC_NONE;
|
||||
DRB_Identity_t drb_id = 0;
|
||||
DRB_Identity_t* pdrb_id = NULL;
|
||||
u8 drb_sn = 0;
|
||||
u8 srb_sn = 5; // fixed sn for SRBs
|
||||
u8 drb_report = 0;
|
||||
long int cnt = 0;
|
||||
rlc_mode_t rlc_type = RLC_NONE;
|
||||
DRB_Identity_t drb_id = 0;
|
||||
DRB_Identity_t* pdrb_id = NULL;
|
||||
u8 drb_sn = 0;
|
||||
u8 srb_sn = 5; // fixed sn for SRBs
|
||||
u8 drb_report = 0;
|
||||
long int cnt = 0;
|
||||
u16 header_compression_profile = 0;
|
||||
u32 action = ACTION_ADD;
|
||||
SRB_ToAddMod_t* srb_toaddmod = NULL;
|
||||
DRB_ToAddMod_t* drb_toaddmod = NULL;
|
||||
u32 action = ACTION_ADD;
|
||||
SRB_ToAddMod_t* srb_toaddmod = NULL;
|
||||
DRB_ToAddMod_t* drb_toaddmod = NULL;
|
||||
|
||||
#ifdef Rel10
|
||||
int i,j;
|
||||
@@ -692,7 +691,7 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
if (drb2release_list != NULL) {
|
||||
for (cnt=0;cnt<drb2add_list->list.count;cnt++) {
|
||||
pdrb_id = drb2release_list->list.array[cnt];
|
||||
rb_id = (index * NB_RB_MAX) + pdrb_id;
|
||||
rb_id = (index * NB_RB_MAX) + *pdrb_id;
|
||||
action = ACTION_REMOVE;
|
||||
pdcp_config_req_asn1 (module_id,
|
||||
frame,
|
||||
|
||||
@@ -91,7 +91,6 @@ extern pthread_mutex_t pdcp_mutex;
|
||||
extern pthread_cond_t pdcp_cond;
|
||||
extern int pdcp_instance_cnt;
|
||||
|
||||
static void *pdcp_thread_main(void* param);
|
||||
int init_pdcp_thread(void);
|
||||
void cleanup_pdcp_thread(void);
|
||||
|
||||
@@ -343,13 +342,14 @@ public_pdcp(int pdcp_module_init ();)
|
||||
public_pdcp(void pdcp_module_cleanup ();)
|
||||
public_pdcp(void pdcp_layer_init ();)
|
||||
public_pdcp(void pdcp_layer_cleanup ();)
|
||||
public_pdcp(int pdcp_netlink_init(void);)
|
||||
|
||||
#define PDCP2NAS_FIFO 21
|
||||
#define NAS2PDCP_FIFO 22
|
||||
|
||||
protected_pdcp_fifo(int pdcp_fifo_flush_sdus (u32_t,u8_t);)
|
||||
protected_pdcp_fifo(int pdcp_fifo_read_input_sdus_remaining_bytes (u32_t,u8_t);)
|
||||
protected_pdcp_fifo(int pdcp_fifo_read_input_sdus(u32_t,u8_t);)
|
||||
protected_pdcp_fifo(int pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag, u8_t UE_index, u8_t eNB_index);)
|
||||
protected_pdcp_fifo(void pdcp_fifo_read_input_sdus_from_otg (u32_t frame, u8_t eNB_flag, u8 UE_index, u8 eNB_index);)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -368,6 +368,13 @@ typedef struct pdcp_data_ind_header_t {
|
||||
int inst;
|
||||
} pdcp_data_ind_header_t;
|
||||
|
||||
struct pdcp_netlink_element_s {
|
||||
pdcp_data_req_header_t pdcp_read_header;
|
||||
|
||||
/* Data part of the message */
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Missing PDU information struct, a copy of this will be enqueued
|
||||
|
||||
@@ -93,8 +93,7 @@ extern Packet_OTG_List *otg_pdcp_buffer;
|
||||
pdcp_data_req_header_t pdcp_read_header;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
pdcp_fifo_flush_sdus (u32_t frame,u8 eNB_flag)
|
||||
int pdcp_fifo_flush_sdus (u32_t frame,u8 eNB_flag)
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -170,7 +169,7 @@ int
|
||||
ret = sendmsg(nas_sock_fd,&nas_msg_tx,0);
|
||||
if (ret<0) {
|
||||
LOG_D(PDCP, "[PDCP_FIFOS] sendmsg returns %d (errno: %d)\n", ret, errno);
|
||||
mac_xface->macphy_exit("");
|
||||
mac_xface->macphy_exit("sendmsg failed for nas_sock_fd\n");
|
||||
break;
|
||||
}
|
||||
#endif // LINUX
|
||||
@@ -350,8 +349,7 @@ int
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int
|
||||
pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag)
|
||||
int pdcp_fifo_read_input_sdus (u32_t frame, u8_t eNB_flag, u8_t UE_index, u8_t eNB_index)
|
||||
{
|
||||
//-----------------------------------------------------------------------------
|
||||
//#ifdef NAS_FIFO
|
||||
@@ -426,11 +424,11 @@ int
|
||||
// } else {
|
||||
//#ifdef PDCP_DEBUG
|
||||
//#ifdef LINUX
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK] Received socket with length %d (nlmsg_len = %d)\n", \
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK] Received socket with length %d (nlmsg_len = %d)\n",
|
||||
// len, nas_nlh->nlmsg_len-sizeof(struct nlmsghdr));
|
||||
//#else
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK] nlmsg_len = %d (%d,%d)\n", \
|
||||
// nas_nlh->nlmsg_len, sizeof(pdcp_data_req_header_t), \
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK] nlmsg_len = %d (%d,%d)\n",
|
||||
// nas_nlh->nlmsg_len, sizeof(pdcp_data_req_header_t),
|
||||
// sizeof(struct nlmsghdr));
|
||||
//#endif
|
||||
//#endif
|
||||
@@ -465,7 +463,7 @@ int
|
||||
//#endif
|
||||
//
|
||||
//#ifdef OAI_EMU
|
||||
// pdcp_read_header.inst = (pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) ? \
|
||||
// pdcp_read_header.inst = (pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) ?
|
||||
// pdcp_read_header.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
|
||||
// pdcp_read_header.inst + oai_emulation.info.first_enb_local;
|
||||
//#else
|
||||
@@ -475,7 +473,7 @@ int
|
||||
// if (pdcp_read_header.rb_id != 0) {
|
||||
// if (pdcp_array[pdcp_read_header.inst][pdcp_read_header.rb_id].instanciated_instance) {
|
||||
//#ifdef PDCP_DEBUG
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK][IP->PDCP] TTI %d, INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n", \
|
||||
// LOG_I(PDCP, "[PDCP][NETLINK][IP->PDCP] TTI %d, INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
|
||||
// frame, pdcp_read_header.inst, len, nas_nlh->nlmsg_len-sizeof(struct nlmsghdr), pdcp_read_header.rb_id);
|
||||
// LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
// frame, pdcp_read_header.inst, pdcp_read_header.data_size, pdcp_read_header.inst, pdcp_read_header.rb_id);
|
||||
@@ -527,8 +525,72 @@ int
|
||||
//#else // neither NAS_NETLINK nor NAS_FIFO
|
||||
// return 0;
|
||||
//#endif // NAS_NETLINK
|
||||
//#endif // NAS_FIFO
|
||||
#ifdef NAS_NETLINK
|
||||
# if defined(ENABLE_PDCP_NETLINK_FIFO)
|
||||
rb_id_t rab_id;
|
||||
|
||||
struct pdcp_netlink_element_s *data = NULL;
|
||||
|
||||
while (pdcp_netlink_dequeue_element(eNB_flag, UE_index, eNB_index, &data) != 0) {
|
||||
if (data->pdcp_read_header.rb_id != 0) {
|
||||
if (pdcp_array[data->pdcp_read_header.inst][data->pdcp_read_header.rb_id%NB_RB_MAX].instanciated_instance) {
|
||||
#ifdef PDCP_DEBUG
|
||||
LOG_D(PDCP, "[MSC_MSG][FRAME %05d][IP][MOD %02d][][--- PDCP_DATA_REQ "
|
||||
"/ %d Bytes --->][PDCP][MOD %02d][RB %02d]\n",
|
||||
frame, data->pdcp_read_header.inst, data->pdcp_read_header.data_size,
|
||||
data->pdcp_read_header.inst, data->pdcp_read_header.rb_id);
|
||||
#endif
|
||||
|
||||
pdcp_data_req(data->pdcp_read_header.inst,
|
||||
frame,
|
||||
eNB_flag,
|
||||
data->pdcp_read_header.rb_id,
|
||||
RLC_MUI_UNDEFINED,
|
||||
RLC_SDU_CONFIRM_NO,
|
||||
data->pdcp_read_header.data_size,
|
||||
data->data,
|
||||
PDCP_DATA_PDU);
|
||||
} else {
|
||||
LOG_E(PDCP, "Received packet for non-instanciated instance %u with rb_id %u\n",
|
||||
data->pdcp_read_header.inst, data->pdcp_read_header.rb_id);
|
||||
}
|
||||
} else if (eNB_flag) {
|
||||
/* rb_id = 0, thus interpreated as broadcast and transported as
|
||||
* multiple unicast is a broadcast packet, we have to send this
|
||||
* packet on all default RABS of all connected UEs
|
||||
*/
|
||||
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
|
||||
for (rab_id = DEFAULT_RAB_ID; rab_id < MAX_RB; rab_id = rab_id + NB_RB_MAX) {
|
||||
if (pdcp_array[pdcp_input_header.inst][rab_id%NB_RB_MAX].instanciated_instance == (pdcp_input_header.inst + 1)) {
|
||||
pdcp_data_req(data->pdcp_read_header.inst,
|
||||
frame,
|
||||
eNB_flag,
|
||||
rab_id,
|
||||
RLC_MUI_UNDEFINED,
|
||||
RLC_SDU_CONFIRM_NO,
|
||||
data->pdcp_read_header.data_size,
|
||||
data->data,
|
||||
PDCP_DATA_PDU);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
|
||||
pdcp_data_req(data->pdcp_read_header.inst,
|
||||
frame, eNB_flag,
|
||||
DEFAULT_RAB_ID,
|
||||
RLC_MUI_UNDEFINED,
|
||||
RLC_SDU_CONFIRM_NO,
|
||||
data->pdcp_read_header.data_size,
|
||||
data->data,
|
||||
PDCP_DATA_PDU);
|
||||
}
|
||||
|
||||
free(data->data);
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
return 0;
|
||||
# else
|
||||
int len = 1;
|
||||
rb_id_t rab_id = 0;
|
||||
|
||||
@@ -546,7 +608,7 @@ int
|
||||
if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
|
||||
LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
|
||||
//return;
|
||||
};
|
||||
}
|
||||
|
||||
if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
|
||||
LOG_I(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
|
||||
@@ -624,7 +686,7 @@ int
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
||||
# endif
|
||||
#else // neither NAS_NETLINK nor NAS_FIFO
|
||||
return 0;
|
||||
#endif // NAS_NETLINK
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/*******************************************************************************
|
||||
|
||||
Eurecom OpenAirInterface
|
||||
Copyright(c) 1999 - 2013 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
|
||||
Openair Tech : openair_tech@eurecom.fr
|
||||
Forums : http://forums.eurecom.fsr/openairinterface
|
||||
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*! \file pdcp_netlink.c
|
||||
* \brief pdcp communication with linux IP interface,
|
||||
* have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink.
|
||||
* Read operation from netlink should be achieved in an asynchronous way to avoid
|
||||
* subframe overload, netlink congestion...
|
||||
* \author Sebastien ROUX
|
||||
* \date 2013
|
||||
* \version 0.1
|
||||
* @ingroup pdcp
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <error.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#include "assertions.h"
|
||||
#include "queue.h"
|
||||
#include "liblfds611.h"
|
||||
|
||||
#include "UTIL/LOG/log.h"
|
||||
#include "UTIL/OCG/OCG.h"
|
||||
#include "UTIL/OCG/OCG_extern.h"
|
||||
#include "LAYER2/MAC/extern.h"
|
||||
|
||||
#include "pdcp.h"
|
||||
#include "pdcp_primitives.h"
|
||||
|
||||
#define PDCP_QUEUE_NB_ELEMENTS 200
|
||||
|
||||
extern char nl_rx_buf[NL_MAX_PAYLOAD];
|
||||
extern struct nlmsghdr *nas_nlh_rx;
|
||||
extern struct iovec nas_iov_rx;
|
||||
extern int nas_sock_fd;
|
||||
extern struct msghdr nas_msg_rx;
|
||||
|
||||
static pthread_t pdcp_netlink_thread;
|
||||
|
||||
/* We use lock-free queues between the User-plane driver running in kernel-space
|
||||
* and the corresponding entity in User-space.
|
||||
* one queue for eNBs (index 0)/one queue for UEs (index 1)
|
||||
*/
|
||||
static struct lfds611_queue_state **pdcp_netlink_queue = NULL;
|
||||
static uint32_t *pdcp_netlink_nb_element = NULL;
|
||||
|
||||
static void *pdcp_netlink_thread_fct(void *arg);
|
||||
|
||||
int pdcp_netlink_init(void) {
|
||||
|
||||
int i, nb_modules;
|
||||
pthread_attr_t attr;
|
||||
struct sched_param sched_param;
|
||||
|
||||
#if defined(USER_MODE) && defined(OAI_EMU)
|
||||
nb_modules = NB_eNB_INST + NB_UE_INST;
|
||||
#else
|
||||
nb_modules = 1;
|
||||
#endif
|
||||
|
||||
pdcp_netlink_queue = calloc(nb_modules, sizeof(struct lfds611_queue_state*));
|
||||
pdcp_netlink_nb_element = malloc(nb_modules * sizeof(uint32_t));
|
||||
|
||||
LOG_I(PDCP, "Creating %d queues for Netlink -> PDCP communication\n",
|
||||
nb_modules);
|
||||
|
||||
for (i = 0; i < nb_modules; i++) {
|
||||
pdcp_netlink_nb_element[i] = 0;
|
||||
if (lfds611_queue_new(&pdcp_netlink_queue[i], PDCP_QUEUE_NB_ELEMENTS) < 0) {
|
||||
LOG_E(PDCP, "Failed to create new FIFO for Netlink -> PDCP communcation instance %d\n", i);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
LOG_E(PDCP, "Failed to initialize pthread attribute for Netlink -> PDCP communication (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sched_param.sched_priority = 10;
|
||||
|
||||
pthread_attr_setschedpolicy(&attr, SCHED_RR);
|
||||
pthread_attr_setschedparam(&attr, &sched_param);
|
||||
|
||||
/* Create one thread that fetchs packets from the netlink.
|
||||
* When the netlink fifo is full, packets are silently dropped, this behaviour
|
||||
* should be avoided if we want a reliable link.
|
||||
*/
|
||||
if (pthread_create(&pdcp_netlink_thread, &attr, pdcp_netlink_thread_fct, NULL) != 0) {
|
||||
LOG_E(PDCP, "Failed to create new thread for Netlink/PDCP communcation (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pdcp_netlink_dequeue_element(uint8_t eNB_flag, uint8_t UE_index, uint8_t eNB_index,
|
||||
struct pdcp_netlink_element_s **data)
|
||||
{
|
||||
int ret = 0;
|
||||
module_id_t module_id;
|
||||
|
||||
#if defined(USER_MODE) && defined(OAI_EMU)
|
||||
module_id = (eNB_flag != 0) ? eNB_index : NB_eNB_INST + UE_index;
|
||||
#else
|
||||
module_id = 0;
|
||||
#endif
|
||||
|
||||
ret = lfds611_queue_dequeue(pdcp_netlink_queue[module_id], (void **)data);
|
||||
|
||||
if (ret != 0) {
|
||||
LOG_D(PDCP, "De-queueing packet for module %d\n", module_id);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
void *pdcp_netlink_thread_fct(void *arg) {
|
||||
int len;
|
||||
struct pdcp_netlink_element_s *new_data = NULL;
|
||||
uint8_t pdcp_read_state;
|
||||
|
||||
pdcp_read_state = 0;
|
||||
memset(nl_rx_buf, 0, NL_MAX_PAYLOAD);
|
||||
|
||||
while (1) {
|
||||
|
||||
len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);
|
||||
|
||||
if (len == 0) {
|
||||
/* Other peer (kernel) has performed an orderly shutdown
|
||||
*/
|
||||
LOG_E(PDCP, "Kernel module has closed the netlink\n");
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (len < 0) {
|
||||
/* There was an error */
|
||||
LOG_E(PDCP, "An error occured while reading netlink (%d:%s)\n",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
/* Normal read.
|
||||
* NOTE: netlink messages can be assembled to form a multipart message
|
||||
*/
|
||||
for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
|
||||
NLMSG_OK(nas_nlh_rx, len);
|
||||
nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {
|
||||
|
||||
/* There is no need to check for nlmsg_type because
|
||||
* the header is not set in our drivers.
|
||||
*/
|
||||
if (pdcp_read_state == 0) {
|
||||
new_data = malloc(sizeof(struct pdcp_netlink_element_s));
|
||||
|
||||
if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
|
||||
pdcp_read_state = 1;
|
||||
memcpy((void *)&new_data->pdcp_read_header, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
|
||||
LOG_I(PDCP, "[NETLINK] RX pdcp_data_req_header_t inst %u, "
|
||||
"rb_id %u data_size %d\n",
|
||||
new_data->pdcp_read_header.inst, new_data->pdcp_read_header.rb_id,
|
||||
new_data->pdcp_read_header.data_size);
|
||||
} else {
|
||||
LOG_E(PDCP, "[NETLINK] WRONG size %d should be sizeof "
|
||||
"(pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n",
|
||||
nas_nlh_rx->nlmsg_len);
|
||||
}
|
||||
} else {
|
||||
pdcp_read_state = 0;
|
||||
|
||||
#ifdef OAI_EMU
|
||||
if (new_data->pdcp_read_header.inst >= oai_emulation.info.nb_enb_local) {
|
||||
new_data->pdcp_read_header.inst = new_data->pdcp_read_header.inst
|
||||
- oai_emulation.info.nb_enb_local + NB_eNB_INST
|
||||
+ oai_emulation.info.first_ue_local;
|
||||
} else {
|
||||
new_data->pdcp_read_header.inst = new_data->pdcp_read_header.inst
|
||||
+ oai_emulation.info.first_enb_local;
|
||||
}
|
||||
#else
|
||||
new_data->pdcp_read_header.inst = 0;
|
||||
#endif
|
||||
new_data->data = malloc(sizeof(uint8_t) * new_data->pdcp_read_header.data_size);
|
||||
/* Copy the data */
|
||||
memcpy(new_data->data, NLMSG_DATA(nas_nlh_rx), new_data->pdcp_read_header.data_size);
|
||||
|
||||
if (pdcp_netlink_nb_element[new_data->pdcp_read_header.inst]
|
||||
> PDCP_QUEUE_NB_ELEMENTS) {
|
||||
LOG_E(PDCP, "[Mod %02x] We reached maximum number of elements in pdcp queue (%d)\n",
|
||||
new_data->pdcp_read_header.inst, pdcp_netlink_nb_element);
|
||||
}
|
||||
|
||||
LOG_D(PDCP, "En-queueing packet for module %d\n", new_data->pdcp_read_header.inst);
|
||||
|
||||
/* Enqueue the element in the right queue */
|
||||
// lfds611_queue_enqueue(pdcp_netlink_queue[new_data->pdcp_read_header.inst], new_data);
|
||||
lfds611_queue_guaranteed_enqueue(pdcp_netlink_queue[new_data->pdcp_read_header.inst], new_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -153,6 +153,9 @@ BOOL pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_b
|
||||
BOOL pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, \
|
||||
u8 bitmap[512], pdcp_control_pdu_for_pdcp_status_report* pdu);
|
||||
|
||||
int pdcp_netlink_dequeue_element(uint8_t eNB_flag, uint8_t UE_index, uint8_t eNB_index,
|
||||
struct pdcp_netlink_element_s **data);
|
||||
|
||||
void pdcp_config_set_security(module_id_t module_id, u32 frame, u8 eNB_flag, rb_id_t rb_id,
|
||||
u16 lc_id, u8 security_mode, u8 *kRRCenc, u8 *kRRCint, u8 *kUPenc);
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ pthread_mutex_t pdcp_mutex;
|
||||
pthread_cond_t pdcp_cond;
|
||||
int pdcp_instance_cnt;
|
||||
|
||||
static void *pdcp_thread_main(void* param);
|
||||
|
||||
static void *pdcp_thread_main(void* param) {
|
||||
|
||||
//u8 eNB_flag = *((u8*)param);
|
||||
|
||||
@@ -69,12 +69,12 @@ typedef struct Packet_otg_elt {
|
||||
} Packet_otg_elt;
|
||||
|
||||
typedef struct Job_element {
|
||||
struct Job_elt *next;
|
||||
struct Job_element *next;
|
||||
Job job;
|
||||
} Job_elt;
|
||||
|
||||
typedef struct Event_element {
|
||||
struct Event_elt *next;
|
||||
struct Event_elt *previous;
|
||||
struct Event_element *next;
|
||||
struct Event_element *previous;
|
||||
Event event;
|
||||
} Event_elt;
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
|
||||
#endif
|
||||
|
||||
#define SECU_DEBUG
|
||||
// #define SECU_DEBUG
|
||||
|
||||
#endif /* OSA_INTERNAL_H_ */
|
||||
|
||||
@@ -24,7 +24,7 @@ void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Derive the keys from kasme and perform truncate on the generated key to
|
||||
* @brief Derive the keys from key and perform truncate on the generated key to
|
||||
* reduce his size to 128 bits. Definition of the derivation function can
|
||||
* be found in 3GPP TS.33401 #A.7
|
||||
* @param[in] alg_type Algorithm distinguisher
|
||||
@@ -41,9 +41,6 @@ int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
|
||||
const uint8_t key[32], uint8_t **out)
|
||||
{
|
||||
uint8_t string[7];
|
||||
#if defined(SECU_DEBUG)
|
||||
int i;
|
||||
#endif
|
||||
|
||||
/* FC */
|
||||
string[0] = FC_ALG_KEY_DER;
|
||||
@@ -79,7 +76,7 @@ int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB)
|
||||
int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB)
|
||||
{
|
||||
uint8_t string[7];
|
||||
|
||||
@@ -107,7 +104,7 @@ int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keN
|
||||
}
|
||||
#endif
|
||||
|
||||
kdf(string, 7, kasme, 32, keNB, 32);
|
||||
kdf(string, 7, key, 32, keNB, 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ double tarmaCalculateSample( double inputSamples[], tarmaProcess_t *proc){
|
||||
*/
|
||||
void tarmaUpdateInputSample (tarmaStream_t *stream){
|
||||
int cnt;
|
||||
LOG_T(OTG,"TARMA_DEBUG: tarmaUpdateInputSample(%d)\n",(int)stream);
|
||||
LOG_T(OTG,"TARMA_DEBUG: tarmaUpdateInputSample(%p)\n", stream);
|
||||
if(stream){
|
||||
for(cnt=0; cnt<TARMA_NUM_PROCESSES; cnt++){
|
||||
stream->tarma_input_samples[cnt]=gaussian_dist(10000,1)-10000;
|
||||
@@ -153,7 +153,7 @@ tarmaStream_t *tarmaInitStream(tarmaStream_t *stream){
|
||||
proc->polyWeight[cntpy]=0;
|
||||
}
|
||||
}
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaInitStream(%d) called\n",(int)stream);
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaInitStream(%p) called\n", stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ void tarmaPrintProc(tarmaProcess_t *proc){
|
||||
char prefix[]="OTG TARMA DEBUG: ";
|
||||
int cntma, cntar;
|
||||
|
||||
printf("%s tarmaPrintProc(%d) called\n",prefix,(int)proc);
|
||||
printf("%s tarmaPrintProc(%p) called\n", prefix, proc);
|
||||
printf("%s ma history:\n",prefix);
|
||||
for(cntma=0; cntma<TARMA_NUM_MA_MAX; cntma++){
|
||||
printf("%s ma[%d]: %f\n",prefix,cntma,proc->maHist[cntma]);
|
||||
@@ -209,7 +209,7 @@ void tarmaPrintStreamInit(tarmaStream_t *stream){
|
||||
tarmaProcess_t *proc;
|
||||
int cntvar, cntp, cntma, cntar, cntpy;
|
||||
|
||||
printf("%s tarmaPrintStreamInit(%d) called\n",prefix,(int)stream);
|
||||
printf("%s tarmaPrintStreamInit(%p) called\n", prefix, stream);
|
||||
for(cntvar=0; cntvar<2; cntvar++){
|
||||
if(cntvar==0){
|
||||
proc=&(stream->tarma_idt);
|
||||
@@ -258,7 +258,7 @@ double tarmaCalculateVideoSample(tarmaVideo_t *video){
|
||||
if(video){
|
||||
proc=&(video->tarma_size);
|
||||
frameidx=video->tarmaVideoGopStructure[video->tarmaVideoFrameNumber];
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateVideoSample(%d) called\n",(int)video);
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaCalculateVideoSample(%p) called\n", video);
|
||||
LOG_D(OTG,"TARMA_DEBUG: frameidx=%d\n",frameidx);
|
||||
if(frameidx>=0 && frameidx<=TARMA_NUM_FRAME_TYPES){
|
||||
for(cntpy=0; cntpy<TARMA_NUM_POLY_MAX; cntpy++){
|
||||
@@ -291,7 +291,7 @@ tarmaVideo_t *tarmaInitVideo(tarmaVideo_t *video){
|
||||
tarmaProcess_t *proc;
|
||||
int cntp, cntma, cntar, cntpy, cntgop, cnttype;
|
||||
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaInitVideo(%d) called\n",(int)video);
|
||||
LOG_D(OTG,"TARMA_DEBUG: tarmaInitVideo(%p) called\n", video);
|
||||
if(video==0){
|
||||
video=(tarmaVideo_t*) malloc(sizeof(tarmaVideo_t));
|
||||
}
|
||||
@@ -382,7 +382,7 @@ void tarmaPrintVideoInit(tarmaVideo_t *video){
|
||||
tarmaProcess_t *proc;
|
||||
int cntp, cntma, cntar, cntpy, cntgop, cnttype;
|
||||
|
||||
printf("%s tarmaPrintVideoInit(%d) called\n",prefix,(int)video);
|
||||
printf("%s tarmaPrintVideoInit(%p) called\n", prefix, video);
|
||||
proc=&(video->tarma_size);
|
||||
printf("%s input process weights\n",prefix);
|
||||
for(cntp=0; cntp<TARMA_NUM_PROCESSES; cntp++){
|
||||
@@ -482,7 +482,7 @@ backgroundStream_t *backgroundStreamInit(backgroundStream_t *stream, double lamb
|
||||
}
|
||||
}
|
||||
|
||||
LOG_D(OTG,"BACKGROUND_USERS DEBUG: backgroundStreamInit(%d) called\n",(int)stream);
|
||||
LOG_D(OTG,"BACKGROUND_USERS DEBUG: backgroundStreamInit(%p) called\n", stream);
|
||||
backgroundPrintStream (stream);
|
||||
return stream;
|
||||
}
|
||||
@@ -496,7 +496,7 @@ backgroundStream_t *backgroundStreamInit(backgroundStream_t *stream, double lamb
|
||||
void backgroundUpdateStream(backgroundStream_t *stream, int ctime){
|
||||
int numNewSessions, cnts, period;
|
||||
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundUpdateStream(stream*=%d,ctime=%d,period=%d) called\n",(int)stream, ctime);
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundUpdateStream(stream*=%p,ctime=%d) called\n", stream, ctime);
|
||||
if(stream){
|
||||
period=ctime-stream->lastUpdateTime;
|
||||
numNewSessions=poisson_dist(stream->meanNumSessions/5710*period);
|
||||
@@ -532,7 +532,7 @@ double backgroundCalculateSize(backgroundStream_t *stream, int ctime, int idt){
|
||||
double mrate=0;
|
||||
|
||||
backgroundUpdateStream(stream, ctime);
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundCalculateSize(stream*=%d,idt=%d,ctime=%d) called\n",(int)stream, idt, ctime);
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundCalculateSize(stream*=%p,idt=%d,ctime=%d) called\n", stream, idt, ctime);
|
||||
if(stream){
|
||||
for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++){
|
||||
if(stream->activeSessions[cnts].endTime>ctime){
|
||||
@@ -554,7 +554,7 @@ double backgroundCalculateSize(backgroundStream_t *stream, int ctime, int idt){
|
||||
void backgroundPrintStream(backgroundStream_t *stream){
|
||||
int cnts;
|
||||
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundPrintStream(%d)\n",(int)stream);
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: backgroundPrintStream(%p)\n", stream);
|
||||
if(stream){
|
||||
LOG_D(OTG,"BACKGROUND DEBUG: meanNumSessions(lambda_n)=%f\n",stream->meanNumSessions);
|
||||
for(cnts=0; cnts<BACKGROUND_NUM_ACTIVE_MAX; cnts++){
|
||||
|
||||
@@ -247,6 +247,7 @@ endif
|
||||
|
||||
CFLAGS += -DENABLE_VCD_FIFO
|
||||
CFLAGS += -DENABLE_NEW_MULTICAST
|
||||
CFLAGS += -DENABLE_PDCP_NETLINK_FIFO
|
||||
# CFLAGS += -DENABLE_LOG_FIFO
|
||||
|
||||
# Check if libpgm is installed and use it if found instead of the unreliable
|
||||
|
||||
@@ -405,7 +405,6 @@ void check_and_adjust_params() {
|
||||
if (ret < 0)
|
||||
LOG_E(EMU,"[INIT] Netlink not available, careful ...\n");
|
||||
|
||||
|
||||
if (ethernet_flag == 1) {
|
||||
oai_emulation.info.master[oai_emulation.info.master_id].nb_ue = oai_emulation.info.nb_ue_local + oai_emulation.info.nb_rn_local;
|
||||
oai_emulation.info.master[oai_emulation.info.master_id].nb_enb = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_rn_local;
|
||||
@@ -434,6 +433,10 @@ void check_and_adjust_params() {
|
||||
NB_eNB_INST = oai_emulation.info.nb_enb_local + oai_emulation.info.nb_enb_remote;
|
||||
NB_RN_INST = oai_emulation.info.nb_rn_local + oai_emulation.info.nb_rn_remote;
|
||||
|
||||
#if defined(ENABLE_PDCP_NETLINK_FIFO)
|
||||
pdcp_netlink_init();
|
||||
#endif
|
||||
|
||||
if (NB_RN_INST > 0 ) {
|
||||
LOG_N(EMU,"Total number of RN %d (local %d, remote %d) mobility (the same as eNB) %s \n", NB_RN_INST,oai_emulation.info.nb_rn_local,oai_emulation.info.nb_rn_remote, oai_emulation.topology_config.mobility.eNB_mobility.eNB_mobility_type.selected_option);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user